1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
|
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _ACAMERA_MANAGER_H
#define _ACAMERA_MANAGER_H
#include <camera/NdkCameraManager.h>
#include <android-base/parseint.h>
#include <android/hardware/ICameraService.h>
#include <android/hardware/BnCameraServiceListener.h>
#include <camera/CameraMetadata.h>
#include <binder/IServiceManager.h>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/AMessage.h>
#include <set>
#include <map>
namespace android {
namespace acam {
/**
* Per-process singleton instance of CameraManger. Shared by all ACameraManager
* instances. Created when first ACameraManager is created and destroyed when
* all ACameraManager instances are deleted.
*
* TODO: maybe CameraManagerGlobal is better suited in libcameraclient?
*/
class CameraManagerGlobal final : public RefBase {
public:
static CameraManagerGlobal& getInstance();
sp<hardware::ICameraService> getCameraService();
void registerAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback);
void unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback);
void registerExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
void unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
/**
* Return camera IDs that support camera2
*/
void getCameraIdList(std::vector<String8> *cameraIds);
private:
sp<hardware::ICameraService> mCameraService;
const int kCameraServicePollDelay = 500000; // 0.5s
const char* kCameraServiceName = "media.camera";
Mutex mLock;
template<class T>
void registerAvailCallback(const T *callback);
class DeathNotifier : public IBinder::DeathRecipient {
public:
explicit DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
protected:
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder>& who);
private:
const wp<CameraManagerGlobal> mCameraManager;
};
sp<DeathNotifier> mDeathNotifier;
class CameraServiceListener final : public hardware::BnCameraServiceListener {
public:
explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
virtual binder::Status onStatusChanged(int32_t status, const String16& cameraId);
virtual binder::Status onPhysicalCameraStatusChanged(int32_t status,
const String16& cameraId, const String16& physicalCameraId);
// Torch API not implemented yet
virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
return binder::Status::ok();
}
virtual binder::Status onCameraAccessPrioritiesChanged();
virtual binder::Status onCameraOpened(const String16&, const String16&) {
return binder::Status::ok();
}
virtual binder::Status onCameraClosed(const String16&) {
return binder::Status::ok();
}
private:
const wp<CameraManagerGlobal> mCameraManager;
};
sp<CameraServiceListener> mCameraServiceListener;
// Wrapper of ACameraManager_AvailabilityCallbacks so we can store it in std::set
struct Callback {
explicit Callback(const ACameraManager_AvailabilityCallbacks *callback) :
mAvailable(callback->onCameraAvailable),
mUnavailable(callback->onCameraUnavailable),
mAccessPriorityChanged(nullptr),
mPhysicalCamAvailable(nullptr),
mPhysicalCamUnavailable(nullptr),
mContext(callback->context) {}
explicit Callback(const ACameraManager_ExtendedAvailabilityCallbacks *callback) :
mAvailable(callback->availabilityCallbacks.onCameraAvailable),
mUnavailable(callback->availabilityCallbacks.onCameraUnavailable),
mAccessPriorityChanged(callback->onCameraAccessPrioritiesChanged),
mPhysicalCamAvailable(callback->onPhysicalCameraAvailable),
mPhysicalCamUnavailable(callback->onPhysicalCameraUnavailable),
mContext(callback->availabilityCallbacks.context) {}
bool operator == (const Callback& other) const {
return (mAvailable == other.mAvailable &&
mUnavailable == other.mUnavailable &&
mAccessPriorityChanged == other.mAccessPriorityChanged &&
mPhysicalCamAvailable == other.mPhysicalCamAvailable &&
mPhysicalCamUnavailable == other.mPhysicalCamUnavailable &&
mContext == other.mContext);
}
bool operator != (const Callback& other) const {
return !(*this == other);
}
bool operator < (const Callback& other) const {
if (*this == other) return false;
if (mContext != other.mContext) return mContext < other.mContext;
if (mPhysicalCamAvailable != other.mPhysicalCamAvailable) {
return mPhysicalCamAvailable < other.mPhysicalCamAvailable;
}
if (mPhysicalCamUnavailable != other.mPhysicalCamUnavailable) {
return mPhysicalCamUnavailable < other.mPhysicalCamUnavailable;
}
if (mAccessPriorityChanged != other.mAccessPriorityChanged) {
return mAccessPriorityChanged < other.mAccessPriorityChanged;
}
if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable;
return mUnavailable < other.mUnavailable;
}
bool operator > (const Callback& other) const {
return (*this != other && !(*this < other));
}
ACameraManager_AvailabilityCallback mAvailable;
ACameraManager_AvailabilityCallback mUnavailable;
ACameraManager_AccessPrioritiesChangedCallback mAccessPriorityChanged;
ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamAvailable;
ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable;
void* mContext;
};
android::Condition mCallbacksCond;
size_t mPendingCallbackCnt = 0;
void onCallbackCalled();
void drainPendingCallbacksLocked();
std::set<Callback> mCallbacks;
// definition of handler and message
enum {
kWhatSendSingleCallback,
kWhatSendSingleAccessCallback,
kWhatSendSinglePhysicalCameraCallback,
};
static const char* kCameraIdKey;
static const char* kPhysicalCameraIdKey;
static const char* kCallbackFpKey;
static const char* kContextKey;
static const nsecs_t kCallbackDrainTimeout;
class CallbackHandler : public AHandler {
public:
CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
void onMessageReceived(const sp<AMessage> &msg) override;
private:
wp<CameraManagerGlobal> mParent;
void notifyParent();
void onMessageReceivedInternal(const sp<AMessage> &msg);
};
sp<CallbackHandler> mHandler;
sp<ALooper> mCbLooper; // Looper thread where callbacks actually happen on
sp<hardware::ICameraService> getCameraServiceLocked();
void onCameraAccessPrioritiesChanged();
void onStatusChanged(int32_t status, const String8& cameraId);
void onStatusChangedLocked(int32_t status, const String8& cameraId);
void onStatusChanged(int32_t status, const String8& cameraId, const String8& physicalCameraId);
void onStatusChangedLocked(int32_t status, const String8& cameraId,
const String8& physicalCameraId);
// Utils for status
static bool validStatus(int32_t status);
static bool isStatusAvailable(int32_t status);
bool supportsCamera2ApiLocked(const String8 &cameraId);
// The sort logic must match the logic in
// libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
struct CameraIdComparator {
bool operator()(const String8& a, const String8& b) const {
uint32_t aUint = 0, bUint = 0;
bool aIsUint = base::ParseUint(a.c_str(), &aUint);
bool bIsUint = base::ParseUint(b.c_str(), &bUint);
// Uint device IDs first
if (aIsUint && bIsUint) {
return aUint < bUint;
} else if (aIsUint) {
return true;
} else if (bIsUint) {
return false;
}
// Simple string compare if both id are not uint
return a < b;
}
};
struct StatusAndHAL3Support {
private:
int32_t status = hardware::ICameraServiceListener::STATUS_NOT_PRESENT;
mutable std::mutex mLock;
std::set<String8> unavailablePhysicalIds;
public:
const bool supportsHAL3 = false;
StatusAndHAL3Support(int32_t st, bool HAL3support):
status(st), supportsHAL3(HAL3support) { };
StatusAndHAL3Support() = default;
bool addUnavailablePhysicalId(const String8& physicalCameraId);
bool removeUnavailablePhysicalId(const String8& physicalCameraId);
int32_t getStatus();
void updateStatus(int32_t newStatus);
std::set<String8> getUnavailablePhysicalIds();
};
// Map camera_id -> status
std::map<String8, StatusAndHAL3Support, CameraIdComparator> mDeviceStatusMap;
// For the singleton instance
static Mutex sLock;
static CameraManagerGlobal* sInstance;
CameraManagerGlobal() {};
~CameraManagerGlobal();
};
} // namespace acam;
} // namespace android;
/**
* ACameraManager opaque struct definition
* Leave outside of android namespace because it's NDK struct
*/
struct ACameraManager {
ACameraManager() :
mGlobalManager(&(android::acam::CameraManagerGlobal::getInstance())) {}
~ACameraManager();
camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
static void deleteCameraIdList(ACameraIdList* cameraIdList);
camera_status_t getCameraCharacteristics(
const char* cameraId, android::sp<ACameraMetadata>* characteristics);
camera_status_t openCamera(const char* cameraId,
ACameraDevice_StateCallbacks* callback,
/*out*/ACameraDevice** device);
private:
enum {
kCameraIdListNotInit = -1
};
android::Mutex mLock;
android::sp<android::acam::CameraManagerGlobal> mGlobalManager;
};
#endif //_ACAMERA_MANAGER_H
|