1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/android/android_image_reader_compat.h"
6
7 #include <dlfcn.h>
8
9 #include "base/android/build_info.h"
10 #include "base/feature_list.h"
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13
14 #define LOAD_FUNCTION(lib, func) \
15 do { \
16 func##_ = reinterpret_cast<p##func>(dlsym(lib, #func)); \
17 if (!func##_) { \
18 DLOG(ERROR) << "Unable to load function " << #func; \
19 return false; \
20 } \
21 } while (0)
22
23 namespace base {
24 namespace android {
25
GetInstance()26 AndroidImageReader& AndroidImageReader::GetInstance() {
27 // C++11 static local variable initialization is
28 // thread-safe.
29 static AndroidImageReader instance;
30 return instance;
31 }
32
IsSupported()33 bool AndroidImageReader::IsSupported() {
34 return is_supported_;
35 }
36
AndroidImageReader()37 AndroidImageReader::AndroidImageReader() : is_supported_(LoadFunctions()) {}
38
LoadFunctions()39 bool AndroidImageReader::LoadFunctions() {
40 // If the Chromium build requires __ANDROID_API__ >= 26 at some
41 // point in the future, we could directly use the global functions instead of
42 // dynamic loading. However, since this would be incompatible with pre-Oreo
43 // devices, this is unlikely to happen in the foreseeable future, so we use
44 // dynamic loading.
45
46 // Functions are not present for android version older than OREO.
47 // Currently we want to enable AImageReader only for android P+ devices.
48 if (base::android::BuildInfo::GetInstance()->sdk_int() <
49 base::android::SDK_VERSION_P) {
50 return false;
51 }
52
53 void* libmediandk = dlopen("libmediandk.so", RTLD_NOW);
54 if (libmediandk == nullptr) {
55 LOG(ERROR) << "Couldnt open libmediandk.so";
56 return false;
57 }
58
59 LOAD_FUNCTION(libmediandk, AImage_delete);
60 LOAD_FUNCTION(libmediandk, AImage_deleteAsync);
61 LOAD_FUNCTION(libmediandk, AImage_getHardwareBuffer);
62 LOAD_FUNCTION(libmediandk, AImage_getWidth);
63 LOAD_FUNCTION(libmediandk, AImage_getHeight);
64 LOAD_FUNCTION(libmediandk, AImage_getCropRect);
65 LOAD_FUNCTION(libmediandk, AImageReader_newWithUsage);
66 LOAD_FUNCTION(libmediandk, AImageReader_setImageListener);
67 LOAD_FUNCTION(libmediandk, AImageReader_delete);
68 LOAD_FUNCTION(libmediandk, AImageReader_getFormat);
69 LOAD_FUNCTION(libmediandk, AImageReader_getWindow);
70 LOAD_FUNCTION(libmediandk, AImageReader_acquireLatestImageAsync);
71 LOAD_FUNCTION(libmediandk, AImageReader_acquireNextImageAsync);
72
73 void* libandroid = dlopen("libandroid.so", RTLD_NOW);
74 if (libandroid == nullptr) {
75 LOG(ERROR) << "Couldnt open libandroid.so";
76 return false;
77 }
78
79 LOAD_FUNCTION(libandroid, ANativeWindow_toSurface);
80
81 return true;
82 }
83
AImage_delete(AImage * image)84 void AndroidImageReader::AImage_delete(AImage* image) {
85 AImage_delete_(image);
86 }
87
AImage_deleteAsync(AImage * image,int releaseFenceFd)88 void AndroidImageReader::AImage_deleteAsync(AImage* image, int releaseFenceFd) {
89 AImage_deleteAsync_(image, releaseFenceFd);
90 }
91
AImage_getHardwareBuffer(const AImage * image,AHardwareBuffer ** buffer)92 media_status_t AndroidImageReader::AImage_getHardwareBuffer(
93 const AImage* image,
94 AHardwareBuffer** buffer) {
95 return AImage_getHardwareBuffer_(image, buffer);
96 }
97
AImage_getWidth(const AImage * image,int32_t * width)98 media_status_t AndroidImageReader::AImage_getWidth(const AImage* image,
99 int32_t* width) {
100 return AImage_getWidth_(image, width);
101 }
102
AImage_getHeight(const AImage * image,int32_t * height)103 media_status_t AndroidImageReader::AImage_getHeight(const AImage* image,
104 int32_t* height) {
105 return AImage_getHeight_(image, height);
106 }
107
AImage_getCropRect(const AImage * image,AImageCropRect * rect)108 media_status_t AndroidImageReader::AImage_getCropRect(const AImage* image,
109 AImageCropRect* rect) {
110 return AImage_getCropRect_(image, rect);
111 }
112
AImageReader_newWithUsage(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,AImageReader ** reader)113 media_status_t AndroidImageReader::AImageReader_newWithUsage(
114 int32_t width,
115 int32_t height,
116 int32_t format,
117 uint64_t usage,
118 int32_t maxImages,
119 AImageReader** reader) {
120 return AImageReader_newWithUsage_(width, height, format, usage, maxImages,
121 reader);
122 }
123
AImageReader_setImageListener(AImageReader * reader,AImageReader_ImageListener * listener)124 media_status_t AndroidImageReader::AImageReader_setImageListener(
125 AImageReader* reader,
126 AImageReader_ImageListener* listener) {
127 return AImageReader_setImageListener_(reader, listener);
128 }
129
AImageReader_delete(AImageReader * reader)130 void AndroidImageReader::AImageReader_delete(AImageReader* reader) {
131 AImageReader_delete_(reader);
132 }
133
AImageReader_getFormat(const AImageReader * reader,int32_t * format)134 media_status_t AndroidImageReader::AImageReader_getFormat(
135 const AImageReader* reader,
136 int32_t* format) {
137 return AImageReader_getFormat_(reader, format);
138 }
139
AImageReader_getWindow(AImageReader * reader,ANativeWindow ** window)140 media_status_t AndroidImageReader::AImageReader_getWindow(
141 AImageReader* reader,
142 ANativeWindow** window) {
143 return AImageReader_getWindow_(reader, window);
144 }
145
AImageReader_acquireLatestImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)146 media_status_t AndroidImageReader::AImageReader_acquireLatestImageAsync(
147 AImageReader* reader,
148 AImage** image,
149 int* acquireFenceFd) {
150 return AImageReader_acquireLatestImageAsync_(reader, image, acquireFenceFd);
151 }
152
AImageReader_acquireNextImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)153 media_status_t AndroidImageReader::AImageReader_acquireNextImageAsync(
154 AImageReader* reader,
155 AImage** image,
156 int* acquireFenceFd) {
157 return AImageReader_acquireNextImageAsync_(reader, image, acquireFenceFd);
158 }
159
ANativeWindow_toSurface(JNIEnv * env,ANativeWindow * window)160 jobject AndroidImageReader::ANativeWindow_toSurface(JNIEnv* env,
161 ANativeWindow* window) {
162 return ANativeWindow_toSurface_(env, window);
163 }
164
165 } // namespace android
166 } // namespace base
167