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
media / audio / android / opensles_wrapper.cc [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
// The file defines the symbols from OpenSLES that android is using. It then
// loads the library dynamically on first use.
// The openSLES API is using constant as part of the API. This file will define
// proxies for those constants and redefine those when the library is first
// loaded. For this, it need to be able to change their content and so import
// the headers without const. This is correct because OpenSLES.h is a C API.
// We include stdint.h here as a workaround for an issue caused by the
// #define const below. The inclusion of OpenSLES headers on newer Android NDK
// versions causes stdint.h to be included, which in turn includes __config.
// This causes the declaration of __sanitizer_annotate_contiguous_container to
// not use const parameters, which causes compile issues when building with
// asan. Including here forces __config to be included while const is still
// untouched.
#include <stdint.h>
#include "base/memory/raw_ptr.h"
#define const
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#undef const
#include <stddef.h>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/native_library.h"
// The constants used in chromium. SLInterfaceID is actually a pointer to
// SLInterfaceID_. Those symbols are defined as extern symbols in the OpenSLES
// headers. They will be initialized to their correct values when the library is
// loaded.
SLInterfaceID SL_IID_ENGINE = NULL;
SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE = NULL;
SLInterfaceID SL_IID_ANDROIDCONFIGURATION = NULL;
SLInterfaceID SL_IID_RECORD = NULL;
SLInterfaceID SL_IID_BUFFERQUEUE = NULL;
SLInterfaceID SL_IID_VOLUME = NULL;
SLInterfaceID SL_IID_PLAY = NULL;
namespace {
// The name of the library to load.
const char kOpenSLLibraryName[] = "libOpenSLES.so";
// Loads the OpenSLES library, and initializes all the proxies.
base::NativeLibrary IntializeLibraryHandle() {
base::NativeLibrary handle =
base::LoadNativeLibrary(base::FilePath(kOpenSLLibraryName), NULL);
if (!handle) {
DLOG(ERROR) << "Unable to load " << kOpenSLLibraryName;
return NULL;
}
// Setup the proxy for each symbol.
// Attach the symbol name to the proxy address.
struct SymbolDefinition {
const char* name;
raw_ptr<SLInterfaceID> sl_iid;
};
// The list of defined symbols.
const SymbolDefinition kSymbols[] = {
{"SL_IID_ENGINE", &SL_IID_ENGINE},
{"SL_IID_ANDROIDSIMPLEBUFFERQUEUE", &SL_IID_ANDROIDSIMPLEBUFFERQUEUE},
{"SL_IID_ANDROIDCONFIGURATION", &SL_IID_ANDROIDCONFIGURATION},
{"SL_IID_RECORD", &SL_IID_RECORD},
{"SL_IID_BUFFERQUEUE", &SL_IID_BUFFERQUEUE},
{"SL_IID_VOLUME", &SL_IID_VOLUME},
{"SL_IID_PLAY", &SL_IID_PLAY}};
for (size_t i = 0; i < sizeof(kSymbols) / sizeof(kSymbols[0]); ++i) {
void* func_ptr =
base::GetFunctionPointerFromNativeLibrary(handle, kSymbols[i].name);
if (!func_ptr) {
DLOG(ERROR) << "Unable to find symbol for " << kSymbols[i].name;
return NULL;
}
memcpy(kSymbols[i].sl_iid, func_ptr, sizeof(SLInterfaceID));
}
return handle;
}
// Returns the handler to the shared library. The library itself will be lazily
// loaded during the first call to this function.
base::NativeLibrary LibraryHandle() {
// The handle is lazily initialized on the first call.
static base::NativeLibrary g_handle = IntializeLibraryHandle();
return g_handle;
}
} // namespace
// Redefine slCreateEngine symbol.
SLresult slCreateEngine(SLObjectItf* engine,
SLuint32 num_options,
SLEngineOption* engine_options,
SLuint32 num_interfaces,
SLInterfaceID* interface_ids,
SLboolean* interfaces_required) {
typedef SLresult (*SlCreateEngineSignature)(SLObjectItf*, SLuint32,
SLEngineOption*, SLuint32,
SLInterfaceID*, SLboolean*);
base::NativeLibrary handle = LibraryHandle();
if (!handle)
return SL_RESULT_INTERNAL_ERROR;
static SlCreateEngineSignature g_sl_create_engine_handle =
reinterpret_cast<SlCreateEngineSignature>(
base::GetFunctionPointerFromNativeLibrary(handle, "slCreateEngine"));
if (!g_sl_create_engine_handle) {
DLOG(ERROR) << "Unable to find symbol for slCreateEngine";
return SL_RESULT_INTERNAL_ERROR;
}
return g_sl_create_engine_handle(engine, num_options, engine_options,
num_interfaces, interface_ids,
interfaces_required);
}