1 /*
2 * Copyright (C) 2023 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 FAILURE_DEBUG_PREFIX "exif"
18
19 #include <vector>
20
21 #if defined(__LP64__)
22 #include <time.h>
23 using Timestamp = time_t;
24 #define TIMESTAMP_TO_TM(timestamp, tm) gmtime_r(timestamp, tm)
25 #else
26 #include <time64.h>
27 using Timestamp = time64_t;
28 #define TIMESTAMP_TO_TM(timestamp, tm) gmtime64_r(timestamp, tm)
29 #endif
30
31 #include <math.h>
32
33 #include <android-base/properties.h>
34 #include <system/camera_metadata.h>
35
36 #include "exif.h"
37 #include "debug.h"
38
39 namespace android {
40 namespace hardware {
41 namespace camera {
42 namespace provider {
43 namespace implementation {
44 namespace exif {
45 namespace {
46
47 struct ExifMemDeleter {
operator ()android::hardware::camera::provider::implementation::exif::__anon57c3d55e0111::ExifMemDeleter48 void operator()(ExifMem* allocator) const {
49 exif_mem_unref(allocator);
50 }
51 };
52
53 typedef std::unique_ptr<ExifMem, ExifMemDeleter> ExifMemPtr;
54
allocateEntry(ExifMem * mem,const ExifTag tag,const ExifFormat format,const size_t numComponents)55 ExifEntry* allocateEntry(ExifMem* mem, const ExifTag tag, const ExifFormat format,
56 const size_t numComponents) {
57 ExifEntry* e = exif_entry_new_mem(mem);
58 const size_t size = numComponents * exif_format_get_size(format);
59 e->data = static_cast<unsigned char*>(exif_mem_alloc(mem, size));
60 e->size = size;
61 e->tag = tag;
62 e->components = numComponents;
63 e->format = format;
64 return e;
65 }
66
appendEntry(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag)67 void appendEntry(ExifData* edata, ExifMem* mem,
68 const ExifIfd ifd, const ExifTag tag) {
69 ExifEntry* e = exif_entry_new_mem(mem);
70 exif_entry_initialize(e, tag);
71 exif_content_add_entry(edata->ifd[ifd], e);
72 exif_entry_unref(e);
73 }
74
appendEntryU8(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint8_t value)75 void appendEntryU8(ExifData* edata, ExifMem* mem,
76 const ExifIfd ifd, const ExifTag tag,
77 const uint8_t value) {
78 ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_BYTE, 1);
79 *e->data = value;
80 exif_content_add_entry(edata->ifd[ifd], e);
81 exif_entry_unref(e);
82 }
83
appendEntryU16(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint16_t value)84 void appendEntryU16(ExifData* edata, ExifMem* mem,
85 const ExifIfd ifd, const ExifTag tag,
86 const uint16_t value) {
87 ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_SHORT, 1);
88 exif_set_short(e->data, exif_data_get_byte_order(edata), value);
89 exif_content_add_entry(edata->ifd[ifd], e);
90 exif_entry_unref(e);
91 }
92
appendEntryU32(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint32_t value)93 void appendEntryU32(ExifData* edata, ExifMem* mem,
94 const ExifIfd ifd, const ExifTag tag,
95 const uint32_t value) {
96 ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_LONG, 1);
97 exif_set_long(e->data, exif_data_get_byte_order(edata), value);
98 exif_content_add_entry(edata->ifd[ifd], e);
99 exif_entry_unref(e);
100 }
101
appendEntryR32(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const ExifRational * src,size_t n)102 void appendEntryR32(ExifData* edata, ExifMem* mem,
103 const ExifIfd ifd, const ExifTag tag,
104 const ExifRational* src, size_t n) {
105 ExifEntry* e = allocateEntry(mem, tag, EXIF_FORMAT_RATIONAL, n);
106
107 for (uint8_t* dst = e->data; n > 0; --n, ++src, dst += sizeof(ExifRational)) {
108 exif_set_rational(dst, exif_data_get_byte_order(edata), *src);
109 }
110
111 exif_content_add_entry(edata->ifd[ifd], e);
112 exif_entry_unref(e);
113 }
114
appendEntryR32(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const uint32_t num,const uint32_t dem)115 void appendEntryR32(ExifData* edata, ExifMem* mem,
116 const ExifIfd ifd, const ExifTag tag,
117 const uint32_t num, const uint32_t dem) {
118 const ExifRational value = { num, dem };
119 appendEntryR32(edata, mem, ifd, tag, &value, 1);
120 }
121
appendEntryS(ExifData * edata,ExifMem * mem,const ExifIfd ifd,const ExifTag tag,const char * value,const size_t size,const ExifFormat format)122 void appendEntryS(ExifData* edata, ExifMem* mem,
123 const ExifIfd ifd, const ExifTag tag,
124 const char* value, const size_t size,
125 const ExifFormat format) {
126 ExifEntry* e = allocateEntry(mem, tag, format, size);
127 memcpy(e->data, value, size);
128 exif_content_add_entry(edata->ifd[ifd], e);
129 exif_entry_unref(e);
130 }
131
convertDegToDegMmSs(double v)132 std::tuple<uint32_t, uint32_t, uint32_t> convertDegToDegMmSs(double v) {
133 const uint32_t ideg = floor(v);
134 v = (v - ideg) * 60;
135 const uint32_t minutes = floor(v);
136 v = (v - minutes) * 60;
137 const uint32_t secondsM = round(v * 1000000);
138 return {ideg, minutes, secondsM};
139 }
140
convertT64ToTm(const int64_t t)141 struct tm convertT64ToTm(const int64_t t) {
142 Timestamp t2 = t;
143 struct tm result;
144 TIMESTAMP_TO_TM(&t2, &result);
145 return result;
146 }
147
148 } // namespace
149
createExifData(const CameraMetadata & metadata,const Rect<uint16_t> size)150 ExifDataPtr createExifData(const CameraMetadata& metadata,
151 const Rect<uint16_t> size) {
152 const camera_metadata_t* const rawMetadata =
153 reinterpret_cast<const camera_metadata_t*>(metadata.metadata.data());
154 camera_metadata_ro_entry_t metadataEntry;
155
156 ExifMemPtr allocator(exif_mem_new_default());
157 ExifDataPtr exifData(exif_data_new_mem(allocator.get()));
158
159 exif_data_set_option(exifData.get(), EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
160 exif_data_set_data_type(exifData.get(), EXIF_DATA_TYPE_COMPRESSED);
161 exif_data_set_byte_order(exifData.get(), EXIF_BYTE_ORDER_INTEL);
162 exif_data_fix(exifData.get());
163
164 {
165 const std::string v = base::GetProperty("ro.product.manufacturer", "");
166 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_0, EXIF_TAG_MAKE,
167 v.c_str(), v.size() + 1, EXIF_FORMAT_ASCII);
168 }
169 {
170 const std::string v = base::GetProperty("ro.product.model", "");
171 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_0, EXIF_TAG_MODEL,
172 v.c_str(), v.size() + 1, EXIF_FORMAT_ASCII);
173 }
174
175 {
176 struct tm now;
177 {
178 time_t t = time(nullptr);
179 localtime_r(&t, &now);
180 }
181
182 char timeStr[20];
183 const int len = snprintf(timeStr, sizeof(timeStr),
184 "%04d:%02d:%02d %02d:%02d:%02d",
185 now.tm_year + 1900, now.tm_mon + 1, now.tm_mday,
186 now.tm_hour, now.tm_min, now.tm_sec) + 1;
187 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_0,
188 EXIF_TAG_DATE_TIME, timeStr, len, EXIF_FORMAT_ASCII);
189 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
190 EXIF_TAG_DATE_TIME_ORIGINAL, timeStr, len, EXIF_FORMAT_ASCII);
191 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
192 EXIF_TAG_DATE_TIME_DIGITIZED, timeStr, len, EXIF_FORMAT_ASCII);
193 }
194 {
195 char ddd[4];
196 const int len = snprintf(ddd, sizeof(ddd), "%03d", 0);
197 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
198 EXIF_TAG_SUB_SEC_TIME, ddd, len, EXIF_FORMAT_ASCII);
199 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
200 EXIF_TAG_SUB_SEC_TIME_ORIGINAL, ddd, len, EXIF_FORMAT_ASCII);
201 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
202 EXIF_TAG_SUB_SEC_TIME_DIGITIZED, ddd, len, EXIF_FORMAT_ASCII);
203 }
204
205 if ((size.width > 0) && (size.height > 0)) {
206 appendEntryU32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
207 EXIF_TAG_PIXEL_X_DIMENSION, size.width);
208 appendEntryU32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
209 EXIF_TAG_PIXEL_Y_DIMENSION, size.width);
210 }
211
212 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_ORIENTATION,
213 &metadataEntry)) {
214 unsigned v;
215 switch (metadataEntry.data.i32[0]) {
216 default:
217 case 0: v = 1; break;
218 case 90: v = 6; break;
219 case 180: v = 3; break;
220 case 270: v = 8; break;
221 }
222
223 appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_0,
224 EXIF_TAG_ORIENTATION, v);
225 }
226
227 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_LENS_APERTURE,
228 &metadataEntry)) {
229 const float v = metadataEntry.data.f[0];
230 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
231 EXIF_TAG_FNUMBER, uint32_t(v * 1000U), 1000U);
232 }
233
234 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_LENS_FOCAL_LENGTH,
235 &metadataEntry)) {
236 const float v = metadataEntry.data.f[0];
237 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
238 EXIF_TAG_FOCAL_LENGTH, uint32_t(v * 1000U), 1000U);
239 }
240
241 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_FLASH_MODE,
242 &metadataEntry)) {
243 const unsigned v =
244 (metadataEntry.data.i32[0] == ANDROID_FLASH_MODE_OFF) ? 0 : 1;
245 appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
246 EXIF_TAG_FLASH, v);
247 }
248
249 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_SENSOR_EXPOSURE_TIME,
250 &metadataEntry)) {
251 int64_t num = metadataEntry.data.i64[0];
252 uint32_t dem = 1000000000U;
253 while (num > std::numeric_limits<uint32_t>::max()) {
254 num /= 10;
255 dem /= 10;
256 }
257
258 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
259 EXIF_TAG_EXPOSURE_TIME, uint32_t(num), dem);
260 }
261
262 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_SENSOR_SENSITIVITY,
263 &metadataEntry)) {
264 appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
265 EXIF_TAG_ISO_SPEED_RATINGS, metadataEntry.data.i32[0]);
266 }
267
268 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_CONTROL_AWB_MODE,
269 &metadataEntry)) {
270 const unsigned v =
271 (metadataEntry.data.i32[0] == ANDROID_CONTROL_AWB_MODE_AUTO) ? 0 : 1;
272
273 appendEntryU16(exifData.get(), allocator.get(), EXIF_IFD_EXIF,
274 EXIF_TAG_WHITE_BALANCE, v);
275 }
276
277 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_GPS_COORDINATES,
278 &metadataEntry)) {
279 {
280 const auto [ideg, minutes, secondsM] = convertDegToDegMmSs(
281 fabs(metadataEntry.data.d[0]));
282 ExifRational degmmss[3] = {{ideg, 1}, {minutes, 1},
283 {secondsM, 1000000}};
284 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
285 static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE),
286 degmmss, 3);
287
288 const char* latRef = (metadataEntry.data.d[0] < 0.0) ? "S" : "N";
289 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
290 static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF),
291 latRef, 2, EXIF_FORMAT_ASCII);
292 }
293 {
294 const auto [ideg, minutes, secondsM] = convertDegToDegMmSs(
295 fabs(metadataEntry.data.d[1]));
296 ExifRational degmmss[3] = {{ideg, 1}, {minutes, 1},
297 {secondsM, 1000000}};
298 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
299 static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE),
300 degmmss, 3);
301
302 const char* latRef = (metadataEntry.data.d[1] < 0.0) ? "W" : "E";
303 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
304 static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF),
305 latRef, 2, EXIF_FORMAT_ASCII);
306 }
307 {
308 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
309 static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE),
310 static_cast<uint32_t>(fabs(metadataEntry.data.d[2]) * 1000.0),
311 1000);
312 appendEntryU8(exifData.get(), allocator.get(), EXIF_IFD_GPS,
313 static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF),
314 (metadataEntry.data.d[2] < 0.0) ? 1 : 0);
315 }
316 }
317
318 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_GPS_TIMESTAMP,
319 &metadataEntry)) {
320 struct tm gpsTime = convertT64ToTm(metadataEntry.data.i64[0]);
321
322 {
323 char yyyymmdd[12];
324 const int len = snprintf(yyyymmdd, sizeof(yyyymmdd), "%04d:%02d:%02d",
325 gpsTime.tm_year + 1900, gpsTime.tm_mon + 1,
326 gpsTime.tm_mday) + 1;
327 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
328 static_cast<ExifTag>(EXIF_TAG_GPS_DATE_STAMP),
329 yyyymmdd, len, EXIF_FORMAT_ASCII);
330 }
331 {
332 ExifRational hhmmss[3] = {{static_cast<ExifLong>(gpsTime.tm_hour), 1},
333 {static_cast<ExifLong>(gpsTime.tm_min), 1},
334 {static_cast<ExifLong>(gpsTime.tm_sec), 1}};
335 appendEntryR32(exifData.get(), allocator.get(), EXIF_IFD_GPS,
336 static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP),
337 hhmmss, 3);
338 }
339 }
340
341 if (!find_camera_metadata_ro_entry(rawMetadata, ANDROID_JPEG_GPS_PROCESSING_METHOD,
342 &metadataEntry)) {
343 // EXIF_FORMAT_UNDEFINED requires this prefix
344 std::vector<char> value = {0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00};
345 value.insert(value.end(),
346 reinterpret_cast<const char*>(metadataEntry.data.u8),
347 reinterpret_cast<const char*>(metadataEntry.data.u8) + metadataEntry.count);
348
349 appendEntryS(exifData.get(), allocator.get(), EXIF_IFD_GPS,
350 static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD),
351 value.data(), value.size(), EXIF_FORMAT_UNDEFINED);
352 }
353
354 return exifData;
355 }
356
exifDataAllocThumbnail(ExifData * const edata,const size_t size)357 void* exifDataAllocThumbnail(ExifData* const edata, const size_t size) {
358 // WARNING: maloc and free must match the functions that are used in
359 // exif_mem_new_default (see above) to manage memory. They will be used in
360 // exif_data_free to deallocate memory allocated here.
361 void* mem = malloc(size);
362 if (mem) {
363 if (edata->data) {
364 free(edata->data);
365 }
366 edata->size = size;
367 edata->data = static_cast<uint8_t*>(mem);
368 }
369 return mem;
370 }
371
operator ()(ExifData * p) const372 void ExifDataDeleter::operator()(ExifData* p) const {
373 exif_data_free(p);
374 }
375
376 } // namespace exif
377 } // namespace implementation
378 } // namespace provider
379 } // namespace camera
380 } // namespace hardware
381 } // namespace android
382