1 /*
2 * Copyright (C) 2022 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 #include "HidlProviderInfo.h"
17 #include "common/HalConversionsTemplated.h"
18 #include "common/CameraProviderInfoTemplated.h"
19
20 #include <com_android_internal_camera_flags.h>
21 #include <cutils/properties.h>
22
23 #include <android/hardware/ICameraService.h>
24 #include <camera_metadata_hidden.h>
25
26 #include "device3/ZoomRatioMapper.h"
27 #include <utils/SessionConfigurationUtilsHidl.h>
28 #include <utils/Trace.h>
29 #include <utils/Utils.h>
30
31 #include <android/hardware/camera/device/3.7/ICameraDevice.h>
32
33 namespace {
34 const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
35 } // anonymous namespace
36
37 namespace android {
38
39 using namespace android::camera3;
40 using namespace hardware::camera;
41 using hardware::camera::common::V1_0::VendorTagSection;
42 using hardware::camera::common::V1_0::Status;
43 using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
44 using hardware::camera2::utils::CameraIdAndSessionConfiguration;
45
46
47 using StatusListener = CameraProviderManager::StatusListener;
48 using HalDeviceStatusType = android::hardware::camera::common::V1_0::CameraDeviceStatus;
49 namespace flags = com::android::internal::camera::flags;
50
51 using hardware::camera::provider::V2_5::DeviceState;
52 using hardware::ICameraService;
53
mapToStatusT(const Status & s)54 status_t HidlProviderInfo::mapToStatusT(const Status& s) {
55 switch(s) {
56 case Status::OK:
57 return OK;
58 case Status::ILLEGAL_ARGUMENT:
59 return BAD_VALUE;
60 case Status::CAMERA_IN_USE:
61 return -EBUSY;
62 case Status::MAX_CAMERAS_IN_USE:
63 return -EUSERS;
64 case Status::METHOD_NOT_SUPPORTED:
65 return UNKNOWN_TRANSACTION;
66 case Status::OPERATION_NOT_SUPPORTED:
67 return INVALID_OPERATION;
68 case Status::CAMERA_DISCONNECTED:
69 return DEAD_OBJECT;
70 case Status::INTERNAL_ERROR:
71 return INVALID_OPERATION;
72 }
73 ALOGW("Unexpected HAL status code %d", eToI(s));
74 return INVALID_OPERATION;
75 }
76
mapToHidlDeviceState(int64_t newState)77 static hardware::hidl_bitfield<DeviceState> mapToHidlDeviceState(int64_t newState) {
78 hardware::hidl_bitfield<DeviceState> newDeviceState{};
79 if (newState & ICameraService::DEVICE_STATE_BACK_COVERED) {
80 newDeviceState |= DeviceState::BACK_COVERED;
81 }
82 if (newState & ICameraService::DEVICE_STATE_FRONT_COVERED) {
83 newDeviceState |= DeviceState::FRONT_COVERED;
84 }
85 if (newState & ICameraService::DEVICE_STATE_FOLDED) {
86 newDeviceState |= DeviceState::FOLDED;
87 }
88 // Only map vendor bits directly
89 uint64_t vendorBits = static_cast<uint64_t>(newState) & 0xFFFFFFFF00000000l;
90 newDeviceState |= vendorBits;
91
92 ALOGV("%s: New device state 0x%" PRIx64, __FUNCTION__, newDeviceState);
93 return newDeviceState;
94 }
95
statusToString(const Status & s)96 const char* statusToString(const Status& s) {
97 switch(s) {
98 case Status::OK:
99 return "OK";
100 case Status::ILLEGAL_ARGUMENT:
101 return "ILLEGAL_ARGUMENT";
102 case Status::CAMERA_IN_USE:
103 return "CAMERA_IN_USE";
104 case Status::MAX_CAMERAS_IN_USE:
105 return "MAX_CAMERAS_IN_USE";
106 case Status::METHOD_NOT_SUPPORTED:
107 return "METHOD_NOT_SUPPORTED";
108 case Status::OPERATION_NOT_SUPPORTED:
109 return "OPERATION_NOT_SUPPORTED";
110 case Status::CAMERA_DISCONNECTED:
111 return "CAMERA_DISCONNECTED";
112 case Status::INTERNAL_ERROR:
113 return "INTERNAL_ERROR";
114 }
115 ALOGW("Unexpected HAL status code %d", eToI(s));
116 return "UNKNOWN_ERROR";
117 }
118
initializeHidlProvider(sp<provider::V2_4::ICameraProvider> & interface,int64_t currentDeviceState)119 status_t HidlProviderInfo::initializeHidlProvider(
120 sp<provider::V2_4::ICameraProvider>& interface,
121 int64_t currentDeviceState) {
122 status_t res = parseProviderName(mProviderName, &mType, &mId);
123 if (res != OK) {
124 ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
125 return BAD_VALUE;
126 }
127 ALOGI("Connecting to new camera provider: %s, isRemote? %d",
128 mProviderName.c_str(), interface->isRemote());
129
130 // Determine minor version
131 mMinorVersion = 4;
132 auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
133 sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
134 if (cast2_6.isOk()) {
135 interface2_6 = cast2_6;
136 if (interface2_6 != nullptr) {
137 mMinorVersion = 6;
138 }
139 }
140 // We need to check again since cast2_6.isOk() succeeds even if the provider
141 // version isn't actually 2.6.
142 if (interface2_6 == nullptr){
143 auto cast2_5 =
144 provider::V2_5::ICameraProvider::castFrom(interface);
145 sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
146 if (cast2_5.isOk()) {
147 interface2_5 = cast2_5;
148 if (interface != nullptr) {
149 mMinorVersion = 5;
150 }
151 }
152 } else {
153 auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
154 if (cast2_7.isOk()) {
155 sp<provider::V2_7::ICameraProvider> interface2_7 = cast2_7;
156 if (interface2_7 != nullptr) {
157 mMinorVersion = 7;
158 }
159 }
160 }
161
162 // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
163 // before setCallback returns
164 hardware::Return<Status> status = interface->setCallback(this);
165 if (!status.isOk()) {
166 ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
167 __FUNCTION__, mProviderName.c_str(), status.description().c_str());
168 return DEAD_OBJECT;
169 }
170 if (status != Status::OK) {
171 ALOGE("%s: Unable to register callbacks with camera provider '%s'",
172 __FUNCTION__, mProviderName.c_str());
173 return mapToStatusT(status);
174 }
175
176 hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
177 if (!linked.isOk()) {
178 ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
179 __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
180 return DEAD_OBJECT;
181 } else if (!linked) {
182 ALOGW("%s: Unable to link to provider '%s' death notifications",
183 __FUNCTION__, mProviderName.c_str());
184 }
185
186 if (!kEnableLazyHal) {
187 // Save HAL reference indefinitely
188 mSavedInterface = interface;
189 } else {
190 mActiveInterface = interface;
191 }
192
193 ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
194 __FUNCTION__, mProviderName.c_str(), mDeviceState);
195 notifyDeviceStateChange(currentDeviceState);
196
197 res = setUpVendorTags();
198 if (res != OK) {
199 ALOGE("%s: Unable to set up vendor tags from provider '%s'",
200 __FUNCTION__, mProviderName.c_str());
201 return res;
202 }
203
204 // Get initial list of camera devices, if any
205 std::vector<std::string> devices;
206 hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
207 Status idStatus,
208 const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
209 status = idStatus;
210 if (status == Status::OK) {
211 for (auto& name : cameraDeviceNames) {
212 uint16_t major, minor;
213 std::string type, id;
214 status_t res = parseDeviceName(name, &major, &minor, &type, &id);
215 if (res != OK) {
216 ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
217 status = Status::INTERNAL_ERROR;
218 } else {
219 devices.push_back(name);
220 mProviderPublicCameraIds.push_back(id);
221 }
222 }
223 } });
224 if (!ret.isOk()) {
225 ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
226 __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
227 return DEAD_OBJECT;
228 }
229 if (status != Status::OK) {
230 ALOGE("%s: Unable to query for camera devices from provider '%s'",
231 __FUNCTION__, mProviderName.c_str());
232 return mapToStatusT(status);
233 }
234
235 // Get list of concurrent streaming camera device combinations
236 if (mMinorVersion >= 6) {
237 res = getConcurrentCameraIdsInternalLocked(interface2_6);
238 if (res != OK) {
239 return res;
240 }
241 }
242
243 ret = interface->isSetTorchModeSupported(
244 [this](auto status, bool supported) {
245 if (status == Status::OK) {
246 mSetTorchModeSupported = supported;
247 }
248 });
249 if (!ret.isOk()) {
250 ALOGE("%s: Transaction error checking torch mode support '%s': %s",
251 __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
252 return DEAD_OBJECT;
253 }
254
255 mIsRemote = interface->isRemote();
256
257 initializeProviderInfoCommon(devices);
258
259 return OK;
260 }
261
setUpVendorTags()262 status_t HidlProviderInfo::setUpVendorTags() {
263 if (mVendorTagDescriptor != nullptr)
264 return OK;
265
266 hardware::hidl_vec<VendorTagSection> vts;
267 Status status;
268 hardware::Return<void> ret;
269 const sp<hardware::camera::provider::V2_4::ICameraProvider> interface =
270 startProviderInterface();
271 if (interface == nullptr) {
272 return DEAD_OBJECT;
273 }
274 ret = interface->getVendorTags(
275 [&](auto s, const auto& vendorTagSecs) {
276 status = s;
277 if (s == Status::OK) {
278 vts = vendorTagSecs;
279 }
280 });
281 if (!ret.isOk()) {
282 ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
283 __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
284 return DEAD_OBJECT;
285 }
286 if (status != Status::OK) {
287 return mapToStatusT(status);
288 }
289
290 // Read all vendor tag definitions into a descriptor
291 status_t res;
292 if ((res = IdlVendorTagDescriptor::createDescriptorFromIdl<
293 hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>,
294 hardware::camera::common::V1_0::VendorTagSection>(vts,
295 /*out*/mVendorTagDescriptor))
296 != OK) {
297 ALOGE("%s: Could not generate descriptor from vendor tag operations,"
298 "received error %s (%d). Camera clients will not be able to use"
299 "vendor tags", __FUNCTION__, strerror(res), res);
300 return res;
301 }
302
303 return OK;
304 }
305
notifyDeviceStateChange(int64_t newDeviceState)306 status_t HidlProviderInfo::notifyDeviceStateChange(int64_t newDeviceState) {
307 mDeviceState = mapToHidlDeviceState(newDeviceState);
308 if (mMinorVersion >= 5) {
309 // Check if the provider is currently active - not going to start it for this notification
310 auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
311 if (interface != nullptr) {
312 // Send current device state
313 auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
314 if (castResult.isOk()) {
315 sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
316 if (interface_2_5 != nullptr) {
317 interface_2_5->notifyDeviceStateChange(mDeviceState);
318 }
319 }
320 }
321 }
322 return OK;
323 }
324
325 sp<device::V3_2::ICameraDevice>
startDeviceInterface(const std::string & name)326 HidlProviderInfo::startDeviceInterface(const std::string &name) {
327 Status status;
328 sp<device::V3_2::ICameraDevice> cameraInterface;
329 hardware::Return<void> ret;
330 const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
331 if (interface == nullptr) {
332 return nullptr;
333 }
334 ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
335 Status s, sp<device::V3_2::ICameraDevice> interface) {
336 status = s;
337 cameraInterface = interface;
338 });
339 if (!ret.isOk()) {
340 ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
341 __FUNCTION__, name.c_str(), ret.description().c_str());
342 return nullptr;
343 }
344 if (status != Status::OK) {
345 ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
346 name.c_str(), statusToString(status));
347 return nullptr;
348 }
349 return cameraInterface;
350 }
351
successfullyStartedProviderInterface()352 bool HidlProviderInfo::successfullyStartedProviderInterface() {
353 return startProviderInterface() != nullptr;
354 }
355
356 const sp<provider::V2_4::ICameraProvider>
startProviderInterface()357 HidlProviderInfo::startProviderInterface() {
358 ATRACE_CALL();
359 ALOGV("Request to start camera provider: %s", mProviderName.c_str());
360 if (mSavedInterface != nullptr) {
361 return mSavedInterface;
362 }
363 if (!kEnableLazyHal) {
364 ALOGE("Bad provider state! Should not be here on a non-lazy HAL!");
365 return nullptr;
366 }
367
368 auto interface = mActiveInterface.promote();
369 if (interface == nullptr) {
370 // Try to get service without starting
371 interface = mManager->mHidlServiceProxy->tryGetService(mProviderName);
372 if (interface == nullptr) {
373 ALOGV("Camera provider actually needs restart, calling getService(%s)",
374 mProviderName.c_str());
375 interface = mManager->mHidlServiceProxy->getService(mProviderName);
376
377 // Set all devices as ENUMERATING, provider should update status
378 // to PRESENT after initializing.
379 // This avoids failing getCameraDeviceInterface_V3_x before devices
380 // are ready.
381 for (auto& device : mDevices) {
382 device->mIsDeviceAvailable = false;
383 }
384
385 interface->setCallback(this);
386 hardware::Return<bool>
387 linked = interface->linkToDeath(this, /*cookie*/ mId);
388 if (!linked.isOk()) {
389 ALOGE(
390 "%s: Transaction error in linking to camera provider '%s' death: %s",
391 __FUNCTION__,
392 mProviderName.c_str(),
393 linked.description().c_str());
394 mManager->removeProvider(std::string(mProviderInstance));
395 return nullptr;
396 } else if (!linked) {
397 ALOGW("%s: Unable to link to provider '%s' death notifications",
398 __FUNCTION__, mProviderName.c_str());
399 }
400 // Send current device state
401 if (mMinorVersion >= 5) {
402 auto castResult =
403 provider::V2_5::ICameraProvider::castFrom(interface);
404 if (castResult.isOk()) {
405 sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
406 if (interface_2_5 != nullptr) {
407 ALOGV("%s: Initial device state for %s: 0x %" PRIx64,
408 __FUNCTION__, mProviderName.c_str(), mDeviceState);
409 interface_2_5->notifyDeviceStateChange(mDeviceState);
410 }
411 }
412 }
413 }
414 mActiveInterface = interface;
415 } else {
416 ALOGV("Camera provider (%s) already in use. Re-using instance.",
417 mProviderName.c_str());
418 }
419
420 return interface;
421 }
422
cameraDeviceStatusChange(const hardware::hidl_string & cameraDeviceName,HalDeviceStatusType newStatus)423 hardware::Return<void> HidlProviderInfo::cameraDeviceStatusChange(
424 const hardware::hidl_string& cameraDeviceName,
425 HalDeviceStatusType newStatus) {
426 cameraDeviceStatusChangeInternal(cameraDeviceName, HalToFrameworkCameraDeviceStatus(newStatus));
427 return hardware::Void();
428 }
429
physicalCameraDeviceStatusChange(const hardware::hidl_string & cameraDeviceName,const hardware::hidl_string & physicalCameraDeviceName,HalDeviceStatusType newStatus)430 hardware::Return<void> HidlProviderInfo::physicalCameraDeviceStatusChange(
431 const hardware::hidl_string& cameraDeviceName,
432 const hardware::hidl_string& physicalCameraDeviceName,
433 HalDeviceStatusType newStatus) {
434 physicalCameraDeviceStatusChangeInternal(cameraDeviceName, physicalCameraDeviceName,
435 HalToFrameworkCameraDeviceStatus(newStatus));
436 return hardware::Void();
437 }
438
torchModeStatusChange(const hardware::hidl_string & cameraDeviceName,hardware::camera::common::V1_0::TorchModeStatus newStatus)439 hardware::Return<void> HidlProviderInfo::torchModeStatusChange(
440 const hardware::hidl_string& cameraDeviceName,
441 hardware::camera::common::V1_0::TorchModeStatus newStatus) {
442
443 torchModeStatusChangeInternal(cameraDeviceName, HalToFrameworkTorchModeStatus(newStatus));
444 return hardware::Void();
445 }
446
serviceDied(uint64_t cookie,const wp<hidl::base::V1_0::IBase> & who)447 void HidlProviderInfo::serviceDied(uint64_t cookie,
448 [[maybe_unused]] const wp<hidl::base::V1_0::IBase>& who) {
449 ALOGI("Camera provider '%s' has died; removing it", mProviderInstance.c_str());
450 if (cookie != mId) {
451 ALOGW("%s: Unexpected serviceDied cookie %" PRIu64 ", expected %" PRIu32,
452 __FUNCTION__, cookie, mId);
453 }
454 mManager->removeProvider(std::string(mProviderInstance));
455 }
456
457 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
initializeDeviceInfo(const std::string & name,const metadata_vendor_id_t tagId,const std::string & id,uint16_t minorVersion)458 HidlProviderInfo::initializeDeviceInfo(
459 const std::string &name, const metadata_vendor_id_t tagId,
460 const std::string &id, uint16_t minorVersion) {
461 Status status;
462
463 auto cameraInterface = startDeviceInterface(name);
464 if (cameraInterface == nullptr) return nullptr;
465
466 common::V1_0::CameraResourceCost resourceCost;
467 cameraInterface->getResourceCost([&status, &resourceCost](
468 Status s, common::V1_0::CameraResourceCost cost) {
469 status = s;
470 resourceCost = cost;
471 });
472 if (status != Status::OK) {
473 ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
474 name.c_str(), statusToString(status));
475 return nullptr;
476 }
477
478 for (auto& conflictName : resourceCost.conflictingDevices) {
479 uint16_t major, minor;
480 std::string type, id;
481 status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
482 if (res != OK) {
483 ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
484 return nullptr;
485 }
486 conflictName = id;
487 }
488
489 return std::unique_ptr<DeviceInfo3>(
490 new HidlDeviceInfo3(name, tagId, id, minorVersion, HalToFrameworkResourceCost(resourceCost),
491 this, mProviderPublicCameraIds, cameraInterface));
492 }
493
reCacheConcurrentStreamingCameraIdsLocked()494 status_t HidlProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
495 if (mMinorVersion < 6) {
496 // Unsupported operation, nothing to do here
497 return OK;
498 }
499 // Check if the provider is currently active - not going to start it up for this notification
500 auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
501 if (interface == nullptr) {
502 ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
503 mProviderName.c_str());
504 return INVALID_OPERATION;
505 }
506 auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
507
508 if (castResult.isOk()) {
509 sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
510 if (interface2_6 != nullptr) {
511 return getConcurrentCameraIdsInternalLocked(interface2_6);
512 } else {
513 // This should not happen since mMinorVersion >= 6
514 ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
515 return UNKNOWN_ERROR;
516 }
517 }
518 return OK;
519 }
520
getConcurrentCameraIdsInternalLocked(sp<provider::V2_6::ICameraProvider> & interface2_6)521 status_t HidlProviderInfo::getConcurrentCameraIdsInternalLocked(
522 sp<provider::V2_6::ICameraProvider> &interface2_6) {
523 if (interface2_6 == nullptr) {
524 ALOGE("%s: null interface provided", __FUNCTION__);
525 return BAD_VALUE;
526 }
527 Status status = Status::OK;
528 hardware::Return<void> ret =
529 interface2_6->getConcurrentStreamingCameraIds([&status, this](
530 Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
531 const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
532 cameraDeviceIdCombinations) {
533 status = concurrentIdStatus;
534 if (status == Status::OK) {
535 mConcurrentCameraIdCombinations.clear();
536 for (auto& combination : cameraDeviceIdCombinations) {
537 std::unordered_set<std::string> deviceIds;
538 for (auto &cameraDeviceId : combination) {
539 deviceIds.insert(cameraDeviceId);
540 }
541 mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
542 }
543 } });
544 if (!ret.isOk()) {
545 ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
546 __FUNCTION__, mProviderName.c_str());
547 return DEAD_OBJECT;
548 }
549 if (status != Status::OK) {
550 ALOGE("%s: Unable to query for camera devices from provider '%s'",
551 __FUNCTION__, mProviderName.c_str());
552 return mapToStatusT(status);
553 }
554 return OK;
555 }
556
HidlDeviceInfo3(const std::string & name,const metadata_vendor_id_t tagId,const std::string & id,uint16_t minorVersion,const CameraResourceCost & resourceCost,sp<CameraProviderManager::ProviderInfo> parentProvider,const std::vector<std::string> & publicCameraIds,sp<hardware::camera::device::V3_2::ICameraDevice> interface)557 HidlProviderInfo::HidlDeviceInfo3::HidlDeviceInfo3(
558 const std::string& name,
559 const metadata_vendor_id_t tagId,
560 const std::string &id, uint16_t minorVersion,
561 const CameraResourceCost& resourceCost,
562 sp<CameraProviderManager::ProviderInfo> parentProvider,
563 const std::vector<std::string>& publicCameraIds,
564 sp<hardware::camera::device::V3_2::ICameraDevice> interface) :
565 DeviceInfo3(name, tagId, id, minorVersion, resourceCost, parentProvider, publicCameraIds) {
566
567 // Get camera characteristics and initialize flash unit availability
568 Status status;
569 hardware::Return<void> ret;
570 ret = interface->getCameraCharacteristics([&status, this](Status s,
571 device::V3_2::CameraMetadata metadata) {
572 status = s;
573 if (s == Status::OK) {
574 camera_metadata_t *buffer =
575 reinterpret_cast<camera_metadata_t*>(metadata.data());
576 size_t expectedSize = metadata.size();
577 int res = validate_camera_metadata_structure(buffer, &expectedSize);
578 if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
579 set_camera_metadata_vendor_id(buffer, mProviderTagid);
580 mCameraCharacteristics = buffer;
581 } else {
582 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
583 status = Status::INTERNAL_ERROR;
584 }
585 }
586 });
587 if (!ret.isOk()) {
588 ALOGE("%s: Transaction error getting camera characteristics for device %s"
589 " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
590 ret.description().c_str());
591 return;
592 }
593 if (status != Status::OK) {
594 ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
595 __FUNCTION__, id.c_str(), statusToString(status), eToI(status));
596 return;
597 }
598
599 if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
600 const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
601 if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
602 for (size_t i = 0; i < stateMap.count; i += 2) {
603 mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
604 }
605 } else {
606 ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
607 stateMap.count);
608 }
609 }
610
611 mSystemCameraKind = getSystemCameraKind();
612
613 status_t res = fixupMonochromeTags();
614 if (OK != res) {
615 ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)",
616 __FUNCTION__, strerror(-res), res);
617 return;
618 }
619
620 res = fixupManualFlashStrengthControlTags(mCameraCharacteristics);
621 if (OK != res) {
622 ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
623 __FUNCTION__, strerror(-res), res);
624 return;
625 }
626
627 auto stat = addDynamicDepthTags();
628 if (OK != stat) {
629 ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat),
630 stat);
631 }
632 res = deriveHeicTags();
633 if (OK != res) {
634 ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
635 __FUNCTION__, strerror(-res), res);
636 }
637
638 if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(mCameraCharacteristics)) {
639 status_t status = addDynamicDepthTags(/*maxResolution*/true);
640 if (OK != status) {
641 ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
642 __FUNCTION__, strerror(-status), status);
643 }
644
645 status = deriveHeicTags(/*maxResolution*/true);
646 if (OK != status) {
647 ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for"
648 "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status);
649 }
650 }
651
652 res = addRotateCropTags();
653 if (OK != res) {
654 ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
655 strerror(-res), res);
656 }
657 res = addAutoframingTags();
658 if (OK != res) {
659 ALOGE("%s: Unable to add default AUTOFRAMING tags: %s (%d)", __FUNCTION__,
660 strerror(-res), res);
661 }
662 res = addPreCorrectionActiveArraySize();
663 if (OK != res) {
664 ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
665 strerror(-res), res);
666 }
667 res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
668 &mCameraCharacteristics, &mSupportNativeZoomRatio);
669 if (OK != res) {
670 ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
671 __FUNCTION__, strerror(-res), res);
672 }
673 res = addReadoutTimestampTag(/*readoutTimestampSupported*/false);
674 if (OK != res) {
675 ALOGE("%s: Unable to add sensorReadoutTimestamp tag: %s (%d)",
676 __FUNCTION__, strerror(-res), res);
677 }
678 if (flags::color_temperature()) {
679 res = addColorCorrectionAvailableModesTag(mCameraCharacteristics);
680 if (OK != res) {
681 ALOGE("%s: Unable to add COLOR_CORRECTION_AVAILABLE_MODES tag: %s (%d)",
682 __FUNCTION__, strerror(-res), res);
683 }
684 }
685
686 if (flags::ae_priority()) {
687 res = addAePriorityModeTags();
688 if (OK != res) {
689 ALOGE("%s: Unable to add CONTROL_AE_AVAILABLE_PRIORITY_MODES tag: %s (%d)",
690 __FUNCTION__, strerror(-res), res);
691 }
692 }
693
694 camera_metadata_entry flashAvailable =
695 mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
696 if (flashAvailable.count == 1 &&
697 flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
698 mHasFlashUnit = true;
699 // Fix up flash strength tags for devices without these keys.
700 res = fixupTorchStrengthTags();
701 if (OK != res) {
702 ALOGE("%s: Unable to add default ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL and"
703 "ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL tags: %s (%d)", __FUNCTION__,
704 strerror(-res), res);
705 }
706 } else {
707 mHasFlashUnit = false;
708 }
709
710 res = addSessionConfigQueryVersionTag();
711 if (OK != res) {
712 ALOGE("%s: Unable to add sessionConfigurationQueryVersion tag: %s (%d)",
713 __FUNCTION__, strerror(-res), res);
714 }
715
716 camera_metadata_entry entry =
717 mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
718 if (entry.count == 1) {
719 mTorchDefaultStrengthLevel = entry.data.i32[0];
720 } else {
721 mTorchDefaultStrengthLevel = 0;
722 }
723 entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
724 if (entry.count == 1) {
725 mTorchMaximumStrengthLevel = entry.data.i32[0];
726 } else {
727 mTorchMaximumStrengthLevel = 0;
728 }
729
730 mTorchStrengthLevel = 0;
731
732 if (!kEnableLazyHal) {
733 // Save HAL reference indefinitely
734 mSavedInterface = interface;
735 }
736
737 queryPhysicalCameraIds();
738
739 // Get physical camera characteristics if applicable
740 auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
741 if (!castResult.isOk()) {
742 ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
743 return;
744 }
745 sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
746 if (interface_3_5 == nullptr) {
747 ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
748 return;
749 }
750
751 if (mIsLogicalCamera) {
752 for (auto& id : mPhysicalIds) {
753 if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
754 mPublicCameraIds.end()) {
755 continue;
756 }
757
758 hardware::hidl_string hidlId(id);
759 ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId,
760 [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) {
761 status = s;
762 if (s == Status::OK) {
763 camera_metadata_t *buffer =
764 reinterpret_cast<camera_metadata_t*>(metadata.data());
765 size_t expectedSize = metadata.size();
766 int res = validate_camera_metadata_structure(buffer, &expectedSize);
767 if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
768 set_camera_metadata_vendor_id(buffer, mProviderTagid);
769 mPhysicalCameraCharacteristics[id] = buffer;
770 } else {
771 ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
772 status = Status::INTERNAL_ERROR;
773 }
774 }
775 });
776
777 if (!ret.isOk()) {
778 ALOGE("%s: Transaction error getting physical camera %s characteristics for"
779 " logical id %s: %s", __FUNCTION__, id.c_str(), mId.c_str(),
780 ret.description().c_str());
781 return;
782 }
783 if (status != Status::OK) {
784 ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
785 __FUNCTION__, id.c_str(), mId.c_str(),
786 statusToString(status), eToI(status));
787 return;
788 }
789
790 res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
791 &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
792 if (OK != res) {
793 ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
794 __FUNCTION__, strerror(-res), res);
795 }
796
797 res = fixupManualFlashStrengthControlTags(mPhysicalCameraCharacteristics[id]);
798 if (OK != res) {
799 ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
800 __FUNCTION__, strerror(-res), res);
801 return;
802 }
803
804 if (flags::color_temperature()) {
805 res = addColorCorrectionAvailableModesTag(mPhysicalCameraCharacteristics[id]);
806 if (OK != res) {
807 ALOGE("%s: Unable to add COLOR_CORRECTION_AVAILABLE_MODES tag: %s (%d)",
808 __FUNCTION__, strerror(-res), res);
809 }
810 }
811 }
812 }
813 }
814
setTorchMode(bool enabled)815 status_t HidlProviderInfo::HidlDeviceInfo3::setTorchMode(bool enabled) {
816 using hardware::camera::common::V1_0::TorchMode;
817 const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
818 Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
819 return mapToStatusT(s);
820 }
821
turnOnTorchWithStrengthLevel(int32_t)822 status_t HidlProviderInfo::HidlDeviceInfo3::turnOnTorchWithStrengthLevel(
823 int32_t /*torchStrengthLevel*/) {
824 ALOGE("%s HIDL does not support turning on torch with variable strength", __FUNCTION__);
825 return INVALID_OPERATION;
826 }
827
getTorchStrengthLevel(int32_t *)828 status_t HidlProviderInfo::HidlDeviceInfo3::getTorchStrengthLevel(int32_t * /*torchStrength*/) {
829 ALOGE("%s HIDL does not support variable torch strength level", __FUNCTION__);
830 return INVALID_OPERATION;
831 }
832
833 sp<hardware::camera::device::V3_2::ICameraDevice>
startDeviceInterface()834 HidlProviderInfo::HidlDeviceInfo3::startDeviceInterface() {
835 Mutex::Autolock l(mDeviceAvailableLock);
836 sp<hardware::camera::device::V3_2::ICameraDevice> device;
837 ATRACE_CALL();
838 if (mSavedInterface == nullptr) {
839 sp<HidlProviderInfo> parentProvider =
840 static_cast<HidlProviderInfo *>(mParentProvider.promote().get());
841 if (parentProvider != nullptr) {
842 // Wait for lazy HALs to confirm device availability
843 if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
844 ALOGV("%s: Wait for external device to become available %s",
845 __FUNCTION__,
846 mId.c_str());
847
848 auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
849 kDeviceAvailableTimeout);
850 if (res != OK) {
851 ALOGE("%s: Failed waiting for device to become available",
852 __FUNCTION__);
853 return nullptr;
854 }
855 }
856
857 device = parentProvider->startDeviceInterface(mName);
858 }
859 } else {
860 device = (hardware::camera::device::V3_2::ICameraDevice *) mSavedInterface.get();
861 }
862 return device;
863 }
864
dumpState(int fd)865 status_t HidlProviderInfo::HidlDeviceInfo3::dumpState(int fd) {
866 native_handle_t* handle = native_handle_create(1,0);
867 handle->data[0] = fd;
868 const sp<hardware::camera::device::V3_2::ICameraDevice> interface =
869 startDeviceInterface();
870 if (interface == nullptr) {
871 return DEAD_OBJECT;
872 }
873 auto ret = interface->dumpState(handle);
874 native_handle_delete(handle);
875 if (!ret.isOk()) {
876 return INVALID_OPERATION;
877 }
878 return OK;
879 }
880
isSessionConfigurationSupported(const SessionConfiguration & configuration,bool overrideForPerfClass,camera3::metadataGetter getMetadata,bool checkSessionParams,bool * status)881 status_t HidlProviderInfo::HidlDeviceInfo3::isSessionConfigurationSupported(
882 const SessionConfiguration &configuration, bool overrideForPerfClass,
883 camera3::metadataGetter getMetadata, bool checkSessionParams, bool *status) {
884
885 if (checkSessionParams) {
886 // HIDL device doesn't support checking session parameters
887 return INVALID_OPERATION;
888 }
889
890 hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
891 bool earlyExit = false;
892 auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
893 mId, mCameraCharacteristics, getMetadata, mPhysicalIds,
894 configuration_3_7, overrideForPerfClass, mProviderTagid,
895 &earlyExit);
896
897 if (!bRes.isOk()) {
898 return UNKNOWN_ERROR;
899 }
900
901 if (earlyExit) {
902 *status = false;
903 return OK;
904 }
905
906 const sp<hardware::camera::device::V3_2::ICameraDevice> interface =
907 startDeviceInterface();
908
909 if (interface == nullptr) {
910 return DEAD_OBJECT;
911 }
912
913 auto castResult_3_5 = device::V3_5::ICameraDevice::castFrom(interface);
914 sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult_3_5;
915 auto castResult_3_7 = device::V3_7::ICameraDevice::castFrom(interface);
916 sp<hardware::camera::device::V3_7::ICameraDevice> interface_3_7 = castResult_3_7;
917
918 status_t res;
919 Status callStatus;
920 ::android::hardware::Return<void> ret;
921 auto halCb =
922 [&callStatus, &status] (Status s, bool combStatus) {
923 callStatus = s;
924 *status = combStatus;
925 };
926 if (interface_3_7 != nullptr) {
927 ret = interface_3_7->isStreamCombinationSupported_3_7(configuration_3_7, halCb);
928 } else if (interface_3_5 != nullptr) {
929 hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
930 bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
931 configuration_3_4, configuration_3_7);
932 if (!success) {
933 *status = false;
934 return OK;
935 }
936 ret = interface_3_5->isStreamCombinationSupported(configuration_3_4, halCb);
937 } else {
938 return INVALID_OPERATION;
939 }
940 if (ret.isOk()) {
941 switch (callStatus) {
942 case Status::OK:
943 // Expected case, do nothing.
944 res = OK;
945 break;
946 case Status::METHOD_NOT_SUPPORTED:
947 res = INVALID_OPERATION;
948 break;
949 default:
950 ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, eToI(callStatus));
951 res = UNKNOWN_ERROR;
952 }
953 } else {
954 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
955 res = UNKNOWN_ERROR;
956 }
957
958 return res;
959 }
960
convertToHALStreamCombinationAndCameraIdsLocked(const std::vector<CameraIdAndSessionConfiguration> & cameraIdsAndSessionConfigs,const std::set<std::string> & perfClassPrimaryCameraIds,int targetSdkVersion,hardware::hidl_vec<CameraIdAndStreamCombination> * halCameraIdsAndStreamCombinations,bool * earlyExit)961 status_t HidlProviderInfo::convertToHALStreamCombinationAndCameraIdsLocked(
962 const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
963 const std::set<std::string>& perfClassPrimaryCameraIds,
964 int targetSdkVersion,
965 hardware::hidl_vec<CameraIdAndStreamCombination> *halCameraIdsAndStreamCombinations,
966 bool *earlyExit) {
967 binder::Status bStatus = binder::Status::ok();
968 std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
969 bool shouldExit = false;
970 status_t res = OK;
971 for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
972 const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
973 hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
974 CameraMetadata deviceInfo;
975 bool overrideForPerfClass =
976 SessionConfigurationUtils::targetPerfClassPrimaryCamera(
977 perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
978 res = mManager->getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo,
979 hardware::ICameraService::ROTATION_OVERRIDE_NONE);
980 if (res != OK) {
981 return res;
982 }
983 camera3::metadataGetter getMetadata =
984 [this](const std::string &id, bool overrideForPerfClass) {
985 CameraMetadata physicalDeviceInfo;
986 mManager->getCameraCharacteristicsLocked(id, overrideForPerfClass,
987 &physicalDeviceInfo, hardware::ICameraService::ROTATION_OVERRIDE_NONE);
988 return physicalDeviceInfo;
989 };
990 std::vector<std::string> physicalCameraIds;
991 mManager->isLogicalCameraLocked(cameraId, &physicalCameraIds);
992 bStatus =
993 SessionConfigurationUtils::convertToHALStreamCombination(
994 cameraIdAndSessionConfig.mSessionConfiguration,
995 cameraId, deviceInfo, getMetadata,
996 physicalCameraIds, streamConfiguration,
997 overrideForPerfClass, mProviderTagid, &shouldExit);
998 if (!bStatus.isOk()) {
999 ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
1000 return INVALID_OPERATION;
1001 }
1002 if (shouldExit) {
1003 *earlyExit = true;
1004 return OK;
1005 }
1006 CameraIdAndStreamCombination halCameraIdAndStream;
1007 halCameraIdAndStream.cameraId = cameraId;
1008 halCameraIdAndStream.streamConfiguration = streamConfiguration;
1009 halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
1010 }
1011 *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
1012 return OK;
1013 }
1014
isConcurrentSessionConfigurationSupported(const std::vector<CameraIdAndSessionConfiguration> & cameraIdsAndSessionConfigs,const std::set<std::string> & perfClassPrimaryCameraIds,int targetSdkVersion,bool * isSupported)1015 status_t HidlProviderInfo::isConcurrentSessionConfigurationSupported(
1016 const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
1017 const std::set<std::string>& perfClassPrimaryCameraIds,
1018 int targetSdkVersion, bool *isSupported) {
1019
1020 hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
1021 bool knowUnsupported = false;
1022 status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
1023 cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
1024 targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
1025 if (res != OK) {
1026 ALOGE("%s unable to convert session configurations provided to HAL stream"
1027 "combinations", __FUNCTION__);
1028 return res;
1029 }
1030 if (knowUnsupported) {
1031 // We got to know the streams aren't valid before doing the HAL
1032 // call itself.
1033 *isSupported = false;
1034 return OK;
1035 }
1036
1037 if (mMinorVersion >= 6) {
1038 // Check if the provider is currently active - not going to start it for this notification
1039 auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
1040 if (interface == nullptr) {
1041 // TODO: This might be some other problem
1042 return INVALID_OPERATION;
1043 }
1044 auto castResult2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
1045 auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
1046 Status callStatus;
1047 auto cb =
1048 [&isSupported, &callStatus](Status s, bool supported) {
1049 callStatus = s;
1050 *isSupported = supported; };
1051
1052 ::android::hardware::Return<void> ret;
1053 sp<provider::V2_7::ICameraProvider> interface_2_7;
1054 sp<provider::V2_6::ICameraProvider> interface_2_6;
1055 if (mMinorVersion >= 7 && castResult2_7.isOk()) {
1056 interface_2_7 = castResult2_7;
1057 if (interface_2_7 != nullptr) {
1058 ret = interface_2_7->isConcurrentStreamCombinationSupported_2_7(
1059 halCameraIdsAndStreamCombinations, cb);
1060 }
1061 } else if (mMinorVersion == 6 && castResult2_6.isOk()) {
1062 interface_2_6 = castResult2_6;
1063 if (interface_2_6 != nullptr) {
1064 hardware::hidl_vec<provider::V2_6::CameraIdAndStreamCombination>
1065 halCameraIdsAndStreamCombinations_2_6;
1066 size_t numStreams = halCameraIdsAndStreamCombinations.size();
1067 halCameraIdsAndStreamCombinations_2_6.resize(numStreams);
1068 for (size_t i = 0; i < numStreams; i++) {
1069 using namespace camera3;
1070 auto const& combination = halCameraIdsAndStreamCombinations[i];
1071 halCameraIdsAndStreamCombinations_2_6[i].cameraId = combination.cameraId;
1072 bool success =
1073 SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
1074 halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
1075 combination.streamConfiguration);
1076 if (!success) {
1077 *isSupported = false;
1078 return OK;
1079 }
1080 }
1081 ret = interface_2_6->isConcurrentStreamCombinationSupported(
1082 halCameraIdsAndStreamCombinations_2_6, cb);
1083 }
1084 }
1085
1086 if (interface_2_7 != nullptr || interface_2_6 != nullptr) {
1087 if (ret.isOk()) {
1088 switch (callStatus) {
1089 case Status::OK:
1090 // Expected case, do nothing.
1091 res = OK;
1092 break;
1093 case Status::METHOD_NOT_SUPPORTED:
1094 res = INVALID_OPERATION;
1095 break;
1096 default:
1097 ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
1098 eToI(callStatus));
1099 res = UNKNOWN_ERROR;
1100 }
1101 } else {
1102 ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
1103 res = UNKNOWN_ERROR;
1104 }
1105 return res;
1106 }
1107 }
1108 // unsupported operation
1109 return INVALID_OPERATION;
1110 }
1111
1112 } //namespace android
1113