• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 "Camera2ClientBase"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20 
21 #include <inttypes.h>
22 
23 #include <utils/Log.h>
24 #include <utils/Trace.h>
25 
26 #include <cutils/properties.h>
27 #include <gui/BufferItem.h>
28 #include <gui/BufferItemConsumer.h>
29 #include <gui/Surface.h>
30 
31 #include <android/hardware/ICameraService.h>
32 #include <camera/CameraSessionStats.h>
33 #include <camera/StringUtils.h>
34 #include <com_android_window_flags.h>
35 #include <com_android_internal_camera_flags.h>
36 
37 #include "common/Camera2ClientBase.h"
38 
39 #include "api2/CameraDeviceClient.h"
40 
41 #include "device3/Camera3Device.h"
42 #include "device3/aidl/AidlCamera3Device.h"
43 #include "device3/hidl/HidlCamera3Device.h"
44 #include "device3/aidl/AidlCamera3SharedDevice.h"
45 
46 namespace android {
47 
48 using namespace camera2;
49 
50 namespace wm_flags = com::android::window::flags;
51 namespace flags = com::android::internal::camera::flags;
52 
53 // Interface used by CameraService
54 
55 template <typename TClientBase>
Camera2ClientBase(const sp<CameraService> & cameraService,const sp<TCamCallbacks> & remoteCallback,std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,const AttributionSourceState & clientAttribution,int callingPid,bool systemNativeClient,const std::string & cameraId,int api1CameraId,int cameraFacing,int sensorOrientation,int servicePid,bool overrideForPerfClass,int rotationOverride,bool sharedMode,bool isVendorClient,bool legacyClient)56 Camera2ClientBase<TClientBase>::Camera2ClientBase(
57         const sp<CameraService>& cameraService, const sp<TCamCallbacks>& remoteCallback,
58         std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
59         std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
60         const AttributionSourceState& clientAttribution, int callingPid, bool systemNativeClient,
61         const std::string& cameraId, int api1CameraId, int cameraFacing, int sensorOrientation,
62         int servicePid, bool overrideForPerfClass, int rotationOverride, bool sharedMode,
63         bool isVendorClient, bool legacyClient)
64     : TClientBase(cameraService, remoteCallback, attributionAndPermissionUtils, clientAttribution,
65                   callingPid, systemNativeClient, cameraId, api1CameraId, cameraFacing,
66                   sensorOrientation, servicePid, rotationOverride, sharedMode),
67       mSharedCameraCallbacks(remoteCallback),
68       mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
69       mDeviceActive(false),
70       mApi1CameraId(api1CameraId) {
71     ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.c_str(),
72           TClientBase::getPackageName().c_str(), TClientBase::mCallingPid,
73           TClientBase::getClientUid());
74 
75     mInitialClientPid = TClientBase::mCallingPid;
76     mOverrideForPerfClass = overrideForPerfClass;
77     mLegacyClient = legacyClient;
78     mIsVendorClient = isVendorClient;
79 }
80 
81 template <typename TClientBase>
checkPid(const char * checkLocation) const82 status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation)
83         const {
84 
85     int callingPid = TClientBase::getCallingPid();
86     if (callingPid == TClientBase::mCallingPid) return NO_ERROR;
87 
88     ALOGE("%s: attempt to use a locked camera from a different process"
89             " (old pid %d, new pid %d)", checkLocation, TClientBase::mCallingPid, callingPid);
90     return PERMISSION_DENIED;
91 }
92 
93 template <typename TClientBase>
initialize(sp<CameraProviderManager> manager,const std::string & monitorTags)94 status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
95         const std::string& monitorTags) {
96     return initializeImpl(manager, monitorTags);
97 }
98 
99 template <typename TClientBase>
100 template <typename TProviderPtr>
initializeImpl(TProviderPtr providerPtr,const std::string & monitorTags)101 status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
102         const std::string& monitorTags) {
103     ATRACE_CALL();
104     ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
105           TClientBase::mCameraIdStr.c_str());
106     status_t res;
107 
108     IPCTransport providerTransport = IPCTransport::INVALID;
109     res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr,
110             &providerTransport);
111     if (res != OK) {
112         return res;
113     }
114     switch (providerTransport) {
115         case IPCTransport::HIDL:
116             mDevice =
117                     new HidlCamera3Device(mCameraServiceProxyWrapper,
118                             TClientBase::mAttributionAndPermissionUtils,
119                             TClientBase::mCameraIdStr, mOverrideForPerfClass,
120                             TClientBase::mRotationOverride, mIsVendorClient,
121                             mLegacyClient);
122             break;
123         case IPCTransport::AIDL:
124             if (flags::camera_multi_client() && TClientBase::mSharedMode) {
125                 mDevice = AidlCamera3SharedDevice::getInstance(mCameraServiceProxyWrapper,
126                             TClientBase::mAttributionAndPermissionUtils,
127                             TClientBase::mCameraIdStr, mOverrideForPerfClass,
128                             TClientBase::mRotationOverride, mIsVendorClient,
129                             mLegacyClient);
130             } else {
131                 mDevice =
132                     new AidlCamera3Device(mCameraServiceProxyWrapper,
133                             TClientBase::mAttributionAndPermissionUtils,
134                             TClientBase::mCameraIdStr, mOverrideForPerfClass,
135                             TClientBase::mRotationOverride, mIsVendorClient,
136                             mLegacyClient);
137             }
138             break;
139         default:
140             ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
141                     TClientBase::mCameraIdStr.c_str());
142             return NO_INIT;
143     }
144     if (mDevice == NULL) {
145         ALOGE("%s: Camera %s: No device connected",
146                 __FUNCTION__, TClientBase::mCameraIdStr.c_str());
147         return NO_INIT;
148     }
149 
150     // Notify camera opening (check op if check_full_attribution_source_chain flag is off).
151     res = TClientBase::notifyCameraOpening();
152     if (res != OK) {
153         TClientBase::notifyCameraClosing();
154         return res;
155     }
156 
157     res = mDevice->initialize(providerPtr, monitorTags);
158     if (res != OK) {
159         ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
160                 __FUNCTION__, TClientBase::mCameraIdStr.c_str(), strerror(-res), res);
161         TClientBase::notifyCameraClosing();
162         return res;
163     }
164 
165     wp<NotificationListener> weakThis(this);
166     res = mDevice->setNotifyCallback(weakThis);
167     if (res != OK) {
168         ALOGE("%s: Camera %s: Unable to set notify callback: %s (%d)",
169                 __FUNCTION__, TClientBase::mCameraIdStr.c_str(), strerror(-res), res);
170         return res;
171     }
172 
173     return OK;
174 }
175 
176 template <typename TClientBase>
~Camera2ClientBase()177 Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
178     ATRACE_CALL();
179 
180     if (!flags::camera_multi_client() || !TClientBase::mDisconnected) {
181         TClientBase::mDestructionStarted = true;
182         disconnect();
183     }
184 
185     ALOGI("%s: Client object's dtor for Camera Id %s completed. Client was: %s (PID %d, UID %u)",
186           __FUNCTION__, TClientBase::mCameraIdStr.c_str(), TClientBase::getPackageName().c_str(),
187           mInitialClientPid, TClientBase::getClientUid());
188 }
189 
190 template <typename TClientBase>
dumpClient(int fd,const Vector<String16> & args)191 status_t Camera2ClientBase<TClientBase>::dumpClient(int fd,
192                                               const Vector<String16>& args) {
193     std::string result;
194     result += fmt::sprintf("Camera2ClientBase[%s] (%p) PID: %d, dump:\n",
195             TClientBase::mCameraIdStr.c_str(),
196             (TClientBase::getRemoteCallback() != NULL ?
197                     (void *)IInterface::asBinder(TClientBase::getRemoteCallback()).get() : NULL),
198             TClientBase::mCallingPid);
199     result += "  State: ";
200 
201     write(fd, result.c_str(), result.size());
202     // TODO: print dynamic/request section from most recent requests
203 
204     return dumpDevice(fd, args);
205 }
206 
207 template <typename TClientBase>
startWatchingTags(const std::string & tags,int out)208 status_t Camera2ClientBase<TClientBase>::startWatchingTags(const std::string &tags, int out) {
209   sp<CameraDeviceBase> device = mDevice;
210   if (!device) {
211     dprintf(out, "  Device is detached");
212     return OK;
213   }
214 
215   return device->startWatchingTags(tags);
216 }
217 
218 template <typename TClientBase>
stopWatchingTags(int out)219 status_t Camera2ClientBase<TClientBase>::stopWatchingTags(int out) {
220   sp<CameraDeviceBase> device = mDevice;
221   if (!device) {
222     dprintf(out, "  Device is detached");
223     return OK;
224   }
225 
226   return device->stopWatchingTags();
227 }
228 
229 template <typename TClientBase>
dumpWatchedEventsToVector(std::vector<std::string> & out)230 status_t Camera2ClientBase<TClientBase>::dumpWatchedEventsToVector(std::vector<std::string> &out) {
231     sp<CameraDeviceBase> device = mDevice;
232     if (!device) {
233         // Nothing to dump if the device is detached
234         return OK;
235     }
236     return device->dumpWatchedEventsToVector(out);
237 }
238 
239 template <typename TClientBase>
dumpDevice(int fd,const Vector<String16> & args)240 status_t Camera2ClientBase<TClientBase>::dumpDevice(
241                                                 int fd,
242                                                 const Vector<String16>& args) {
243     std::string result;
244 
245     result = "  Device dump:\n";
246     write(fd, result.c_str(), result.size());
247 
248     sp<CameraDeviceBase> device = mDevice;
249     if (!device.get()) {
250         result = "  *** Device is detached\n";
251         write(fd, result.c_str(), result.size());
252         return NO_ERROR;
253     }
254 
255     status_t res = device->dump(fd, args);
256     if (res != OK) {
257         result = fmt::sprintf("   Error dumping device: %s (%d)",
258                 strerror(-res), res);
259         write(fd, result.c_str(), result.size());
260     }
261 
262     return NO_ERROR;
263 }
264 
265 // ICameraClient2BaseUser interface
266 
267 template <typename TClientBase>
disconnect()268 binder::Status Camera2ClientBase<TClientBase>::disconnect() {
269 
270    if (!flags::camera_multi_client() || !TClientBase::mDisconnected) {
271        return disconnectImpl();
272    }
273    return binder::Status::ok();
274 }
275 
276 template <typename TClientBase>
disconnectImpl()277 binder::Status Camera2ClientBase<TClientBase>::disconnectImpl() {
278     ATRACE_CALL();
279     ALOGD("Camera %s: start to disconnect", TClientBase::mCameraIdStr.c_str());
280     Mutex::Autolock icl(mBinderSerializationLock);
281 
282     ALOGD("Camera %s: serializationLock acquired", TClientBase::mCameraIdStr.c_str());
283     binder::Status res = binder::Status::ok();
284     // Allow both client and the media server to disconnect at all times
285     int callingPid = TClientBase::getCallingPid();
286     if (callingPid != TClientBase::mCallingPid &&
287         callingPid != TClientBase::mServicePid) return res;
288 
289     ALOGD("Camera %s: Shutting down", TClientBase::mCameraIdStr.c_str());
290 
291     // Before detaching the device, cache the info from current open session.
292     // The disconnected check avoids duplication of info and also prevents
293     // deadlock while acquiring service lock in cacheDump.
294     if (!TClientBase::mDisconnected) {
295         ALOGD("Camera %s: start to cacheDump", TClientBase::mCameraIdStr.c_str());
296         Camera2ClientBase::getCameraService()->cacheDump();
297     }
298 
299     detachDevice();
300 
301     CameraService::BasicClient::disconnect();
302 
303     ALOGV("Camera %s: Shut down complete", TClientBase::mCameraIdStr.c_str());
304 
305     return res;
306 }
307 
308 template <typename TClientBase>
detachDevice()309 void Camera2ClientBase<TClientBase>::detachDevice() {
310     if (mDevice == 0) return;
311     if (flags::camera_multi_client() && TClientBase::mSharedMode) {
312         mDevice->disconnectClient(TClientBase::getClientCallingPid());
313     } else {
314         mDevice->disconnect();
315     }
316 
317     ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.c_str());
318 }
319 
320 template <typename TClientBase>
connect(const sp<TCamCallbacks> & client)321 status_t Camera2ClientBase<TClientBase>::connect(
322         const sp<TCamCallbacks>& client) {
323     ATRACE_CALL();
324     ALOGV("%s: E", __FUNCTION__);
325     Mutex::Autolock icl(mBinderSerializationLock);
326 
327     if (TClientBase::mCallingPid != 0 &&
328         TClientBase::getCallingPid() != TClientBase::mCallingPid) {
329 
330         ALOGE("%s: Camera %s: Connection attempt from pid %d; "
331                 "current locked to pid %d",
332                 __FUNCTION__,
333                 TClientBase::mCameraIdStr.c_str(),
334                 TClientBase::getCallingPid(),
335                 TClientBase::mCallingPid);
336         return BAD_VALUE;
337     }
338 
339     TClientBase::mCallingPid = TClientBase::getCallingPid();
340 
341     TClientBase::mRemoteCallback = client;
342     mSharedCameraCallbacks = client;
343 
344     return OK;
345 }
346 
347 /** Device-related methods */
348 
349 template <typename TClientBase>
notifyError(int32_t errorCode,const CaptureResultExtras & resultExtras)350 void Camera2ClientBase<TClientBase>::notifyError(
351         int32_t errorCode,
352         const CaptureResultExtras& resultExtras) {
353     ALOGE("Error condition %d reported by HAL, requestId %" PRId32, errorCode,
354           resultExtras.requestId);
355 }
356 
357 template <typename TClientBase>
notifyClientSharedAccessPriorityChanged(bool primaryClient)358 void Camera2ClientBase<TClientBase>::notifyClientSharedAccessPriorityChanged(bool primaryClient) {
359     ALOGV("%s Camera %s access priorities changed for client %d primaryClient=%d", __FUNCTION__,
360             TClientBase::mCameraIdStr.c_str(), TClientBase::getClientUid(), primaryClient);
361 }
362 
363 template <typename TClientBase>
notifyPhysicalCameraChange(const std::string & physicalId)364 void Camera2ClientBase<TClientBase>::notifyPhysicalCameraChange(const std::string &physicalId) {
365     using android::hardware::ICameraService;
366     // We're only interested in this notification if rotationOverride is turned on.
367     if (TClientBase::mRotationOverride == ICameraService::ROTATION_OVERRIDE_NONE) {
368         return;
369     }
370 
371     auto physicalCameraMetadata = mDevice->infoPhysical(physicalId);
372     auto orientationEntry = physicalCameraMetadata.find(ANDROID_SENSOR_ORIENTATION);
373 
374     if (orientationEntry.count == 1) {
375         int orientation = orientationEntry.data.i32[0];
376         int rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
377         bool landscapeSensor =  (orientation == 0 || orientation == 180);
378         if (((TClientBase::mRotationOverride ==
379                 ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT) && landscapeSensor) ||
380                         ((wm_flags::enable_camera_compat_for_desktop_windowing() &&
381                                 TClientBase::mRotationOverride ==
382                                 ICameraService::ROTATION_OVERRIDE_ROTATION_ONLY)
383                                 && !landscapeSensor)) {
384             rotateAndCropMode = ANDROID_SCALER_ROTATE_AND_CROP_90;
385         }
386 
387         static_cast<TClientBase *>(this)->setRotateAndCropOverride(rotateAndCropMode,
388                                                                    /*fromHal*/ true);
389     }
390 }
391 
392 template <typename TClientBase>
notifyActive(float maxPreviewFps)393 status_t Camera2ClientBase<TClientBase>::notifyActive(float maxPreviewFps) {
394     if (!mDeviceActive) {
395         status_t res = TClientBase::startCameraStreamingOps();
396         if (res != OK) {
397             ALOGE("%s: Camera %s: Error starting camera streaming ops: %d", __FUNCTION__,
398                     TClientBase::mCameraIdStr.c_str(), res);
399             return res;
400         }
401         mCameraServiceProxyWrapper->logActive(TClientBase::mCameraIdStr, maxPreviewFps);
402     }
403     mDeviceActive = true;
404 
405     ALOGV("Camera device is now active");
406     return OK;
407 }
408 
409 template <typename TClientBase>
notifyIdleWithUserTag(int64_t requestCount,int64_t resultErrorCount,bool deviceError,std::pair<int32_t,int32_t> mostRequestedFpsRange,const std::vector<hardware::CameraStreamStats> & streamStats,const std::string & userTag,int videoStabilizationMode,bool usedUltraWide,bool usedZoomOverride)410 void Camera2ClientBase<TClientBase>::notifyIdleWithUserTag(
411         int64_t requestCount, int64_t resultErrorCount, bool deviceError,
412         std::pair<int32_t, int32_t> mostRequestedFpsRange,
413         const std::vector<hardware::CameraStreamStats>& streamStats,
414         const std::string& userTag, int videoStabilizationMode, bool usedUltraWide,
415         bool usedZoomOverride) {
416     if (mDeviceActive) {
417         status_t res = TClientBase::finishCameraStreamingOps();
418         if (res != OK) {
419             ALOGE("%s: Camera %s: Error finishing streaming ops: %d", __FUNCTION__,
420                     TClientBase::mCameraIdStr.c_str(), res);
421         }
422         mCameraServiceProxyWrapper->logIdle(TClientBase::mCameraIdStr,
423                 requestCount, resultErrorCount, deviceError, userTag, videoStabilizationMode,
424                 usedUltraWide, usedZoomOverride, mostRequestedFpsRange, streamStats);
425     }
426     mDeviceActive = false;
427 
428     ALOGV("Camera device is now idle");
429 }
430 
431 template <typename TClientBase>
notifyShutter(const CaptureResultExtras & resultExtras,nsecs_t timestamp)432 void Camera2ClientBase<TClientBase>::notifyShutter(
433                 [[maybe_unused]] const CaptureResultExtras& resultExtras,
434                 [[maybe_unused]] nsecs_t timestamp) {
435     ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
436             __FUNCTION__, resultExtras.requestId, timestamp);
437 }
438 
439 template <typename TClientBase>
notifyAutoFocus(uint8_t newState,int triggerId)440 void Camera2ClientBase<TClientBase>::notifyAutoFocus([[maybe_unused]] uint8_t newState,
441                                                      [[maybe_unused]] int triggerId) {
442     ALOGV("%s: Autofocus state now %d, last trigger %d",
443           __FUNCTION__, newState, triggerId);
444 
445 }
446 
447 template <typename TClientBase>
notifyAutoExposure(uint8_t newState,int triggerId)448 void Camera2ClientBase<TClientBase>::notifyAutoExposure([[maybe_unused]] uint8_t newState,
449                                                         [[maybe_unused]] int triggerId) {
450     ALOGV("%s: Autoexposure state now %d, last trigger %d",
451             __FUNCTION__, newState, triggerId);
452 }
453 
454 template <typename TClientBase>
notifyAutoWhitebalance(uint8_t newState,int triggerId)455 void Camera2ClientBase<TClientBase>::notifyAutoWhitebalance(
456                 [[maybe_unused]] uint8_t newState,
457                 [[maybe_unused]] int triggerId) {
458     ALOGV("%s: Auto-whitebalance state now %d, last trigger %d",
459             __FUNCTION__, newState, triggerId);
460 }
461 
462 template <typename TClientBase>
notifyPrepared(int streamId)463 void Camera2ClientBase<TClientBase>::notifyPrepared([[maybe_unused]] int streamId) {
464     ALOGV("%s: Stream %d now prepared",
465             __FUNCTION__, streamId);
466 }
467 
468 template <typename TClientBase>
notifyRequestQueueEmpty()469 void Camera2ClientBase<TClientBase>::notifyRequestQueueEmpty() {
470 
471     ALOGV("%s: Request queue now empty", __FUNCTION__);
472 }
473 
474 template <typename TClientBase>
notifyRepeatingRequestError(long lastFrameNumber)475 void Camera2ClientBase<TClientBase>::notifyRepeatingRequestError(
476             [[maybe_unused]] long lastFrameNumber) {
477     ALOGV("%s: Repeating request was stopped. Last frame number is %ld",
478             __FUNCTION__, lastFrameNumber);
479 }
480 
481 template <typename TClientBase>
getCameraId() const482 int Camera2ClientBase<TClientBase>::getCameraId() const {
483     return mApi1CameraId;
484 }
485 
486 template <typename TClientBase>
getCameraDevice()487 const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() {
488     return mDevice;
489 }
490 
491 template <typename TClientBase>
getCameraService()492 const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() {
493     return TClientBase::sCameraService;
494 }
495 
496 template <typename TClientBase>
Lock(SharedCameraCallbacks & client)497 Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::Lock(
498         SharedCameraCallbacks &client) :
499 
500         mRemoteCallback(client.mRemoteCallback),
501         mSharedClient(client) {
502 
503     mSharedClient.mRemoteCallbackLock.lock();
504 }
505 
506 template <typename TClientBase>
~Lock()507 Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::~Lock() {
508     mSharedClient.mRemoteCallbackLock.unlock();
509 }
510 
511 template <typename TClientBase>
SharedCameraCallbacks(const sp<TCamCallbacks> & client)512 Camera2ClientBase<TClientBase>::SharedCameraCallbacks::SharedCameraCallbacks(
513         const sp<TCamCallbacks>&client) :
514 
515         mRemoteCallback(client) {
516 }
517 
518 template <typename TClientBase>
519 typename Camera2ClientBase<TClientBase>::SharedCameraCallbacks&
operator =(const sp<TCamCallbacks> & client)520 Camera2ClientBase<TClientBase>::SharedCameraCallbacks::operator=(
521         const sp<TCamCallbacks>&client) {
522 
523     Mutex::Autolock l(mRemoteCallbackLock);
524     mRemoteCallback = client;
525     return *this;
526 }
527 
528 template <typename TClientBase>
clear()529 void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() {
530     Mutex::Autolock l(mRemoteCallbackLock);
531     mRemoteCallback.clear();
532 }
533 
534 template <typename TClientBase>
injectCamera(const std::string & injectedCamId,sp<CameraProviderManager> manager)535 status_t Camera2ClientBase<TClientBase>::injectCamera(const std::string& injectedCamId,
536         sp<CameraProviderManager> manager) {
537     return mDevice->injectCamera(injectedCamId, manager);
538 }
539 
540 template <typename TClientBase>
stopInjection()541 status_t Camera2ClientBase<TClientBase>::stopInjection() {
542     return mDevice->stopInjection();
543 }
544 
545 template <typename TClientBase>
injectSessionParams(const CameraMetadata & sessionParams)546 status_t Camera2ClientBase<TClientBase>::injectSessionParams(
547     const CameraMetadata& sessionParams) {
548     return mDevice->injectSessionParams(sessionParams);
549 }
550 
551 template class Camera2ClientBase<CameraService::Client>;
552 template class Camera2ClientBase<CameraDeviceClientBase>;
553 
554 } // namespace android
555