Merge "Revert "[audiopolicy][enginebase] Fix schema verification""
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index c66dea2..f4fb626 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -41,22 +41,24 @@
#include <utils/Timers.h>
#include <utils/Trace.h>
+#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>
-#include <ui/DisplayInfo.h>
+#include <media/MediaCodecBuffer.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormatPriv.h>
#include <media/NdkMediaMuxer.h>
#include <media/openmax/OMX_IVCommon.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/PersistentSurface.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <mediadrm/ICrypto.h>
-#include <media/MediaCodecBuffer.h>
+#include <ui/DisplayConfig.h>
+#include <ui/DisplayState.h>
#include "screenrecord.h"
#include "Overlay.h"
@@ -66,7 +68,7 @@
using android::ALooper;
using android::AMessage;
using android::AString;
-using android::DisplayInfo;
+using android::DisplayConfig;
using android::FrameOutput;
using android::IBinder;
using android::IGraphicBufferProducer;
@@ -270,14 +272,15 @@
static status_t setDisplayProjection(
SurfaceComposerClient::Transaction& t,
const sp<IBinder>& dpy,
- const DisplayInfo& displayInfo) {
+ const ui::DisplayState& displayState) {
+ const ui::Size& viewport = displayState.viewport;
// Set the region of the layer stack we're interested in, which in our
// case is "all of it".
- Rect layerStackRect(displayInfo.viewportW, displayInfo.viewportH);
+ Rect layerStackRect(viewport);
// We need to preserve the aspect ratio of the display.
- float displayAspect = (float) displayInfo.viewportH / (float) displayInfo.viewportW;
+ float displayAspect = viewport.getHeight() / static_cast<float>(viewport.getWidth());
// Set the way we map the output onto the display surface (which will
@@ -336,15 +339,16 @@
* Configures the virtual display. When this completes, virtual display
* frames will start arriving from the buffer producer.
*/
-static status_t prepareVirtualDisplay(const DisplayInfo& displayInfo,
+static status_t prepareVirtualDisplay(
+ const ui::DisplayState& displayState,
const sp<IGraphicBufferProducer>& bufferProducer,
sp<IBinder>* pDisplayHandle) {
sp<IBinder> dpy = SurfaceComposerClient::createDisplay(
String8("ScreenRecorder"), false /*secure*/);
SurfaceComposerClient::Transaction t;
t.setDisplaySurface(dpy, bufferProducer);
- setDisplayProjection(t, dpy, displayInfo);
- t.setDisplayLayerStack(dpy, displayInfo.layerStack);
+ setDisplayProjection(t, dpy, displayState);
+ t.setDisplayLayerStack(dpy, displayState.layerStack);
t.apply();
*pDisplayHandle = dpy;
@@ -421,7 +425,6 @@
uint32_t debugNumFrames = 0;
int64_t startWhenNsec = systemTime(CLOCK_MONOTONIC);
int64_t endWhenNsec = startWhenNsec + seconds_to_nanoseconds(gTimeLimitSec);
- DisplayInfo displayInfo;
Vector<int64_t> timestamps;
bool firstFrame = true;
@@ -478,16 +481,16 @@
//
// Polling for changes is inefficient and wrong, but the
// useful stuff is hard to get at without a Dalvik VM.
- err = SurfaceComposerClient::getDisplayInfo(display,
- &displayInfo);
+ ui::DisplayState displayState;
+ err = SurfaceComposerClient::getDisplayState(display, &displayState);
if (err != NO_ERROR) {
- ALOGW("getDisplayInfo(main) failed: %d", err);
- } else if (orientation != displayInfo.orientation) {
- ALOGD("orientation changed, now %s", toCString(displayInfo.orientation));
+ ALOGW("getDisplayState() failed: %d", err);
+ } else if (orientation != displayState.orientation) {
+ ALOGD("orientation changed, now %s", toCString(displayState.orientation));
SurfaceComposerClient::Transaction t;
- setDisplayProjection(t, virtualDpy, displayInfo);
+ setDisplayProjection(t, virtualDpy, displayState);
t.apply();
- orientation = displayInfo.orientation;
+ orientation = displayState.orientation;
}
}
@@ -682,26 +685,34 @@
return NAME_NOT_FOUND;
}
- DisplayInfo displayInfo;
- err = SurfaceComposerClient::getDisplayInfo(display, &displayInfo);
+ ui::DisplayState displayState;
+ err = SurfaceComposerClient::getDisplayState(display, &displayState);
if (err != NO_ERROR) {
- fprintf(stderr, "ERROR: unable to get display characteristics\n");
+ fprintf(stderr, "ERROR: unable to get display state\n");
return err;
}
+ DisplayConfig displayConfig;
+ err = SurfaceComposerClient::getActiveDisplayConfig(display, &displayConfig);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ERROR: unable to get display config\n");
+ return err;
+ }
+
+ const ui::Size& viewport = displayState.viewport;
if (gVerbose) {
printf("Display is %dx%d @%.2ffps (orientation=%s), layerStack=%u\n",
- displayInfo.viewportW, displayInfo.viewportH, displayInfo.fps,
- toCString(displayInfo.orientation), displayInfo.layerStack);
+ viewport.getWidth(), viewport.getHeight(), displayConfig.refreshRate,
+ toCString(displayState.orientation), displayState.layerStack);
fflush(stdout);
}
// Encoder can't take odd number as config
if (gVideoWidth == 0) {
- gVideoWidth = floorToEven(displayInfo.viewportW);
+ gVideoWidth = floorToEven(viewport.getWidth());
}
if (gVideoHeight == 0) {
- gVideoHeight = floorToEven(displayInfo.viewportH);
+ gVideoHeight = floorToEven(viewport.getHeight());
}
// Configure and start the encoder.
@@ -709,7 +720,7 @@
sp<FrameOutput> frameOutput;
sp<IGraphicBufferProducer> encoderInputSurface;
if (gOutputFormat != FORMAT_FRAMES && gOutputFormat != FORMAT_RAW_FRAMES) {
- err = prepareEncoder(displayInfo.fps, &encoder, &encoderInputSurface);
+ err = prepareEncoder(displayConfig.refreshRate, &encoder, &encoderInputSurface);
if (err != NO_ERROR && !gSizeSpecified) {
// fallback is defined for landscape; swap if we're in portrait
@@ -722,8 +733,7 @@
gVideoWidth, gVideoHeight, newWidth, newHeight);
gVideoWidth = newWidth;
gVideoHeight = newHeight;
- err = prepareEncoder(displayInfo.fps, &encoder,
- &encoderInputSurface);
+ err = prepareEncoder(displayConfig.refreshRate, &encoder, &encoderInputSurface);
}
}
if (err != NO_ERROR) return err;
@@ -770,7 +780,7 @@
// Configure virtual display.
sp<IBinder> dpy;
- err = prepareVirtualDisplay(displayInfo, bufferProducer, &dpy);
+ err = prepareVirtualDisplay(displayState, bufferProducer, &dpy);
if (err != NO_ERROR) {
if (encoder != NULL) encoder->release();
return err;
@@ -853,8 +863,7 @@
}
} else {
// Main encoder loop.
- err = runEncoder(encoder, muxer, rawFp, display, dpy,
- displayInfo.orientation);
+ err = runEncoder(encoder, muxer, rawFp, display, dpy, displayState.orientation);
if (err != NO_ERROR) {
fprintf(stderr, "Encoder failed (err=%d)\n", err);
// fall through to cleanup
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index f2d1c29..c26e0b9 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -39,7 +39,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/Surface.h>
-#include <ui/DisplayInfo.h>
+#include <ui/DisplayConfig.h>
static void usage(const char *me) {
fprintf(stderr, "usage: %s [-a] use audio\n"
@@ -414,11 +414,12 @@
const sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
CHECK(display != nullptr);
- DisplayInfo info;
- CHECK_EQ(SurfaceComposerClient::getDisplayInfo(display, &info), NO_ERROR);
+ DisplayConfig config;
+ CHECK_EQ(SurfaceComposerClient::getActiveDisplayConfig(display, &config), NO_ERROR);
- ssize_t displayWidth = info.w;
- ssize_t displayHeight = info.h;
+ const ui::Size& resolution = config.resolution;
+ const ssize_t displayWidth = resolution.getWidth();
+ const ssize_t displayHeight = resolution.getHeight();
ALOGV("display is %zd x %zd\n", displayWidth, displayHeight);
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
index 66302b0..b894545 100644
--- a/cmds/stagefright/mediafilter.cpp
+++ b/cmds/stagefright/mediafilter.cpp
@@ -34,7 +34,7 @@
#include <media/stagefright/NuMediaExtractor.h>
#include <media/stagefright/RenderScriptWrapper.h>
#include <OMX_IVCommon.h>
-#include <ui/DisplayInfo.h>
+#include <ui/DisplayConfig.h>
#include "RenderScript.h"
#include "ScriptC_argbtorgba.h"
@@ -751,11 +751,12 @@
const android::sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
CHECK(display != nullptr);
- DisplayInfo info;
- CHECK_EQ(SurfaceComposerClient::getDisplayInfo(display, &info), NO_ERROR);
+ DisplayConfig config;
+ CHECK_EQ(SurfaceComposerClient::getActiveDisplayConfig(display, &config), NO_ERROR);
- ssize_t displayWidth = info.w;
- ssize_t displayHeight = info.h;
+ const ui::Size& resolution = config.resolution;
+ const ssize_t displayWidth = resolution.getWidth();
+ const ssize_t displayHeight = resolution.getHeight();
ALOGV("display is %zd x %zd", displayWidth, displayHeight);
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 5b29158..250d26b 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -42,7 +42,7 @@
#include <gui/Surface.h>
#include <fcntl.h>
-#include <ui/DisplayInfo.h>
+#include <ui/DisplayConfig.h>
using namespace android;
@@ -321,11 +321,12 @@
const sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
CHECK(display != nullptr);
- DisplayInfo info;
- CHECK_EQ(SurfaceComposerClient::getDisplayInfo(display, &info), NO_ERROR);
+ DisplayConfig config;
+ CHECK_EQ(SurfaceComposerClient::getActiveDisplayConfig(display, &config), NO_ERROR);
- ssize_t displayWidth = info.w;
- ssize_t displayHeight = info.h;
+ const ui::Size& resolution = config.resolution;
+ const ssize_t displayWidth = resolution.getWidth();
+ const ssize_t displayHeight = resolution.getHeight();
ALOGV("display is %zd x %zd\n", displayWidth, displayHeight);
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index a9928b3..f111f81 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -206,10 +206,23 @@
std::mutex mMutex;
sp<ClientManager> mSenderManager;
sp<IClientManager> mReceiverManager;
- int64_t mReceiverConnectionId;
- int64_t mSourceConnectionId;
- std::chrono::steady_clock::time_point mLastSent;
std::chrono::steady_clock::duration mRefreshInterval;
+
+ struct Connection {
+ int64_t receiverConnectionId;
+ std::chrono::steady_clock::time_point lastSent;
+ Connection(int64_t receiverConnectionId,
+ std::chrono::steady_clock::time_point lastSent)
+ : receiverConnectionId(receiverConnectionId),
+ lastSent(lastSent) {
+ }
+ };
+
+ // Map of connections.
+ //
+ // The key is the connection id. One sender-receiver pair may have multiple
+ // connections.
+ std::map<int64_t, Connection> mConnections;
};
// std::list<std::unique_ptr<C2Work>> -> WorkBundle
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index 04fa59c..c73cb52 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -969,8 +969,6 @@
const sp<IClientManager>& receiverManager,
std::chrono::steady_clock::duration refreshInterval)
: mReceiverManager(receiverManager),
- mSourceConnectionId(0),
- mLastSent(std::chrono::steady_clock::now()),
mRefreshInterval(refreshInterval) {
}
@@ -980,6 +978,7 @@
std::lock_guard<std::mutex> lock(mMutex);
if (mReceiverManager != receiverManager) {
mReceiverManager = receiverManager;
+ mConnections.clear();
}
mRefreshInterval = refreshInterval;
}
@@ -987,12 +986,16 @@
ResultStatus DefaultBufferPoolSender::send(
const std::shared_ptr<BufferPoolData>& bpData,
BufferStatusMessage* bpMessage) {
+ int64_t connectionId = bpData->mConnectionId;
+ if (connectionId == 0) {
+ LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
+ return ResultStatus::CRITICAL_ERROR;
+ }
+ std::lock_guard<std::mutex> lock(mMutex);
if (!mReceiverManager) {
LOG(ERROR) << "No access to receiver's BufferPool.";
return ResultStatus::NOT_FOUND;
}
- ResultStatus rs;
- std::lock_guard<std::mutex> lock(mMutex);
if (!mSenderManager) {
mSenderManager = ClientManager::getInstance();
if (!mSenderManager) {
@@ -1000,52 +1003,61 @@
return ResultStatus::CRITICAL_ERROR;
}
}
- int64_t connectionId = bpData->mConnectionId;
+
+ int64_t receiverConnectionId{0};
+ auto foundConnection = mConnections.find(connectionId);
+ bool isNewConnection = foundConnection == mConnections.end();
std::chrono::steady_clock::time_point now =
std::chrono::steady_clock::now();
- std::chrono::steady_clock::duration interval = now - mLastSent;
- if (mSourceConnectionId == 0 ||
- mSourceConnectionId != connectionId ||
- interval > mRefreshInterval) {
+ if (isNewConnection ||
+ (now - foundConnection->second.lastSent > mRefreshInterval)) {
// Initialize the bufferpool connection.
- mSourceConnectionId = connectionId;
- if (mSourceConnectionId == 0) {
- return ResultStatus::CRITICAL_ERROR;
- }
-
- int64_t receiverConnectionId;
- rs = mSenderManager->registerSender(mReceiverManager,
- connectionId,
- &receiverConnectionId);
+ ResultStatus rs =
+ mSenderManager->registerSender(mReceiverManager,
+ connectionId,
+ &receiverConnectionId);
if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
LOG(WARNING) << "registerSender -- returned error: "
<< static_cast<int32_t>(rs)
<< ".";
return rs;
+ } else if (receiverConnectionId == 0) {
+ LOG(WARNING) << "registerSender -- "
+ "invalid receiver connection id (0).";
+ return ResultStatus::CRITICAL_ERROR;
} else {
- mReceiverConnectionId = receiverConnectionId;
+ if (isNewConnection) {
+ foundConnection = mConnections.try_emplace(
+ connectionId, receiverConnectionId, now).first;
+ } else {
+ foundConnection->second.receiverConnectionId = receiverConnectionId;
+ }
}
+ } else {
+ receiverConnectionId = foundConnection->second.receiverConnectionId;
}
uint64_t transactionId;
int64_t timestampUs;
- rs = mSenderManager->postSend(
- mReceiverConnectionId, bpData, &transactionId, ×tampUs);
+ ResultStatus rs = mSenderManager->postSend(
+ receiverConnectionId, bpData, &transactionId, ×tampUs);
if (rs != ResultStatus::OK) {
LOG(ERROR) << "ClientManager::postSend -- returned error: "
<< static_cast<int32_t>(rs)
<< ".";
+ mConnections.erase(foundConnection);
return rs;
}
if (!bpMessage) {
LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
+ mConnections.erase(foundConnection);
return ResultStatus::CRITICAL_ERROR;
}
- bpMessage->connectionId = mReceiverConnectionId;
+ bpMessage->connectionId = receiverConnectionId;
bpMessage->bufferId = bpData->mId;
bpMessage->transactionId = transactionId;
bpMessage->timestampUs = timestampUs;
- mLastSent = now;
+ foundConnection->second.lastSent = now;
return rs;
}
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index 59c8200..a00812b 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -652,12 +652,13 @@
}
mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
- memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
+
if (!mSampleTimeEntries) {
ALOGE("Cannot allocate sample entry table with %llu entries.",
(unsigned long long)mNumSampleSizes);
return;
}
+ memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
uint32_t sampleIndex = 0;
uint64_t sampleTime = 0;
diff --git a/media/libaaudio/examples/input_monitor/Android.bp b/media/libaaudio/examples/input_monitor/Android.bp
index 5d399b5..d8c5843 100644
--- a/media/libaaudio/examples/input_monitor/Android.bp
+++ b/media/libaaudio/examples/input_monitor/Android.bp
@@ -5,7 +5,6 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
- pack_relocations: false,
}
cc_test {
@@ -15,5 +14,4 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
- pack_relocations: false,
}
diff --git a/media/libaaudio/examples/loopback/Android.bp b/media/libaaudio/examples/loopback/Android.bp
index 53e5020..5b7d956 100644
--- a/media/libaaudio/examples/loopback/Android.bp
+++ b/media/libaaudio/examples/loopback/Android.bp
@@ -9,5 +9,4 @@
"libaudioutils",
],
header_libs: ["libaaudio_example_utils"],
- pack_relocations: false,
}
diff --git a/media/libaaudio/examples/write_sine/Android.bp b/media/libaaudio/examples/write_sine/Android.bp
index cc80861..aa25e67 100644
--- a/media/libaaudio/examples/write_sine/Android.bp
+++ b/media/libaaudio/examples/write_sine/Android.bp
@@ -4,7 +4,6 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
- pack_relocations: false,
}
cc_test {
@@ -13,5 +12,4 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
- pack_relocations: false,
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index ce38414..cc78ec1 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -1518,7 +1518,8 @@
case SET_SUPPORTED_SYSTEM_USAGES:
case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
- case GET_DEVICES_FOR_ATTRIBUTES: {
+ case GET_DEVICES_FOR_ATTRIBUTES:
+ case SET_ALLOWED_CAPTURE_POLICY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index 6d46363..e71ea2c 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -49,7 +49,7 @@
mDataSource = nullptr;
}
-class DataSourceUnwrapper {
+class MidiIoWrapper::DataSourceUnwrapper {
public:
explicit DataSourceUnwrapper(CDataSource *csource) {
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index 7beb619..0cdd4ad 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -22,7 +22,6 @@
namespace android {
struct CDataSource;
-class DataSourceUnwrapper;
class MidiIoWrapper {
public:
@@ -41,6 +40,7 @@
int mFd;
off64_t mBase;
int64_t mLength;
+ class DataSourceUnwrapper;
DataSourceUnwrapper *mDataSource;
EAS_FILE mEasFile;
};
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/libmediatranscoding/TranscodingClientManager.cpp
index 5013a51..7252437 100644
--- a/media/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/libmediatranscoding/TranscodingClientManager.cpp
@@ -17,23 +17,31 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "TranscodingClientManager"
+#include <inttypes.h>
#include <media/TranscodingClientManager.h>
#include <utils/Log.h>
namespace android {
-class DeathNotifier;
using Status = ::ndk::ScopedAStatus;
// static
-sp<TranscodingClientManager> TranscodingClientManager::getInstance() {
- static sp<TranscodingClientManager> sInstance = new TranscodingClientManager();
- return sInstance;
+TranscodingClientManager& TranscodingClientManager::getInstance() {
+ static TranscodingClientManager gInstance{};
+ return gInstance;
+}
+
+// static
+void TranscodingClientManager::BinderDiedCallback(void* cookie) {
+ int32_t clientId = static_cast<int32_t>(reinterpret_cast<intptr_t>(cookie));
+ ALOGD("Client %" PRId32 " is dead", clientId);
+ // Don't check for pid validity since we know it's already dead.
+ TranscodingClientManager& manager = TranscodingClientManager::getInstance();
+ manager.removeClient(clientId);
}
TranscodingClientManager::TranscodingClientManager()
- : mDeathRecipient(AIBinder_DeathRecipient_new(
- TranscodingClientManager::DeathNotifier::BinderDiedCallback)) {
+ : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
ALOGD("TranscodingClientManager started");
}
@@ -77,14 +85,13 @@
status_t TranscodingClientManager::addClient(std::unique_ptr<ClientInfo> client) {
// Validate the client.
- if (client == nullptr || client->mClientId <= 0 || client->mClientPid <= 0 ||
- client->mClientUid <= 0 || client->mClientOpPackageName.empty() ||
+ if (client == nullptr || client->mClientId < 0 || client->mClientPid < 0 ||
+ client->mClientUid < 0 || client->mClientOpPackageName.empty() ||
client->mClientOpPackageName == "") {
ALOGE("Invalid client");
return BAD_VALUE;
}
- ALOGD("Adding client id %d %s", client->mClientId, client->mClientOpPackageName.c_str());
std::scoped_lock lock{mLock};
// Check if the client already exists.
@@ -93,10 +100,11 @@
return ALREADY_EXISTS;
}
- // Listen to the death of the client.
- client->mDeathNotifier = new DeathNotifier();
+ ALOGD("Adding client id %d pid: %d uid: %d %s", client->mClientId, client->mClientPid,
+ client->mClientUid, client->mClientOpPackageName.c_str());
+
AIBinder_linkToDeath(client->mClient->asBinder().get(), mDeathRecipient.get(),
- client->mDeathNotifier.get());
+ reinterpret_cast<void*>(client->mClientId));
// Adds the new client to the map.
mClientIdToClientInfoMap[client->mClientId] = std::move(client);
@@ -120,7 +128,7 @@
// Check if the client still live. If alive, unlink the death.
if (client) {
AIBinder_unlinkToDeath(client->asBinder().get(), mDeathRecipient.get(),
- it->second->mDeathNotifier.get());
+ reinterpret_cast<void*>(clientId));
}
// Erase the entry.
@@ -134,13 +142,4 @@
return mClientIdToClientInfoMap.size();
}
-// static
-void TranscodingClientManager::DeathNotifier::BinderDiedCallback(void* cookie) {
- int32_t* pClientId = static_cast<int32_t*>(cookie);
- ALOGD("Client %d is dead", *pClientId);
- // Don't check for pid validity since we know it's already dead.
- sp<TranscodingClientManager> manager = TranscodingClientManager::getInstance();
- manager->removeClient(*pClientId);
-}
-
} // namespace android
diff --git a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl b/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
index 798300a..07b6c1a 100644
--- a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
+++ b/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
@@ -75,6 +75,11 @@
boolean unregisterClient(in int clientId);
/**
+ * Returns the number of clients. This is used for debugging.
+ */
+ int getNumOfClients();
+
+ /**
* Submits a transcoding request to MediaTranscodingService.
*
* @param clientId assigned Id of the client.
diff --git a/media/libmediatranscoding/include/media/TranscodingClientManager.h b/media/libmediatranscoding/include/media/TranscodingClientManager.h
index dbf837c..eec120a 100644
--- a/media/libmediatranscoding/include/media/TranscodingClientManager.h
+++ b/media/libmediatranscoding/include/media/TranscodingClientManager.h
@@ -45,11 +45,7 @@
* TODO(hkuang): Hook up with ResourceManager for resource management.
* TODO(hkuang): Hook up with MediaMetrics to log all the transactions.
*/
-class TranscodingClientManager : public RefBase {
- private:
- // Forward declare it as it will be used in ClientInfo below.
- class DeathNotifier;
-
+class TranscodingClientManager {
public:
virtual ~TranscodingClientManager();
@@ -67,8 +63,6 @@
int32_t mClientUid;
/* Package name of the client. */
std::string mClientOpPackageName;
- /* Listener for the death of the client. */
- sp<DeathNotifier> mDeathNotifier;
ClientInfo(const std::shared_ptr<ITranscodingServiceClient>& client, int64_t clientId,
int32_t pid, int32_t uid, const std::string& opPackageName)
@@ -76,8 +70,7 @@
mClientId(clientId),
mClientPid(pid),
mClientUid(uid),
- mClientOpPackageName(opPackageName),
- mDeathNotifier(nullptr) {}
+ mClientOpPackageName(opPackageName) {}
};
/**
@@ -121,26 +114,17 @@
friend class MediaTranscodingService;
friend class TranscodingClientManagerTest;
- class DeathNotifier : public RefBase {
- public:
- DeathNotifier() = default;
-
- ~DeathNotifier() = default;
-
- // Implement death recipient
- static void BinderDiedCallback(void* cookie);
- };
-
/** Get the singleton instance of the TranscodingClientManager. */
- static sp<TranscodingClientManager> getInstance();
+ static TranscodingClientManager& getInstance();
TranscodingClientManager();
+ static void BinderDiedCallback(void* cookie);
+
mutable std::mutex mLock;
std::unordered_map<int32_t, std::unique_ptr<ClientInfo>> mClientIdToClientInfoMap
GUARDED_BY(mLock);
- std::vector<sp<DeathNotifier>> mDeathNotifiers GUARDED_BY(mLock);
::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
};
diff --git a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
index 97c8919..5d2419d 100644
--- a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
+++ b/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
@@ -87,15 +87,11 @@
class TranscodingClientManagerTest : public ::testing::Test {
public:
- TranscodingClientManagerTest() { ALOGD("TranscodingClientManagerTest created"); }
+ TranscodingClientManagerTest() : mClientManager(TranscodingClientManager::getInstance()) {
+ ALOGD("TranscodingClientManagerTest created");
+ }
void SetUp() override {
- mClientManager = TranscodingClientManager::getInstance();
- if (mClientManager == nullptr) {
- ALOGE("Failed to acquire TranscodingClientManager.");
- return;
- }
-
::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
mService = IMediaTranscodingService::fromBinder(binder);
if (mService == nullptr) {
@@ -108,13 +104,12 @@
void TearDown() override {
ALOGI("TranscodingClientManagerTest tear down");
- mClientManager = nullptr;
mService = nullptr;
}
~TranscodingClientManagerTest() { ALOGD("TranscodingClientManagerTest destroyed"); }
- sp<TranscodingClientManager> mClientManager = nullptr;
+ TranscodingClientManager& mClientManager;
std::shared_ptr<ITranscodingServiceClient> mTestClient = nullptr;
std::shared_ptr<IMediaTranscodingService> mService = nullptr;
};
@@ -129,7 +124,7 @@
client, kInvalidClientId, kClientPid, kClientUid, kClientOpPackageName);
// Add the client to the manager and expect failure.
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err != OK);
}
@@ -143,7 +138,7 @@
client, kClientId, kInvalidClientPid, kClientUid, kClientOpPackageName);
// Add the client to the manager and expect failure.
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err != OK);
}
@@ -157,7 +152,7 @@
client, kClientId, kClientPid, kInvalidClientUid, kClientOpPackageName);
// Add the client to the manager and expect failure.
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err != OK);
}
@@ -171,7 +166,7 @@
client, kClientId, kClientPid, kClientUid, kInvalidClientOpPackageName);
// Add the client to the manager and expect failure.
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err != OK);
}
@@ -183,13 +178,13 @@
std::make_unique<TranscodingClientManager::ClientInfo>(
client1, kClientId, kClientPid, kClientUid, kClientOpPackageName);
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err == OK);
- size_t numOfClients = mClientManager->getNumOfClients();
+ size_t numOfClients = mClientManager.getNumOfClients();
EXPECT_EQ(numOfClients, 1);
- err = mClientManager->removeClient(kClientId);
+ err = mClientManager.removeClient(kClientId);
EXPECT_TRUE(err == OK);
}
@@ -201,13 +196,13 @@
std::make_unique<TranscodingClientManager::ClientInfo>(
client1, kClientId, kClientPid, kClientUid, kClientOpPackageName);
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err == OK);
- err = mClientManager->addClient(std::move(clientInfo));
+ err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err != OK);
- err = mClientManager->removeClient(kClientId);
+ err = mClientManager.removeClient(kClientId);
EXPECT_TRUE(err == OK);
}
@@ -219,7 +214,7 @@
std::make_unique<TranscodingClientManager::ClientInfo>(
client1, kClientId, kClientPid, kClientUid, kClientOpPackageName);
- status_t err = mClientManager->addClient(std::move(clientInfo1));
+ status_t err = mClientManager.addClient(std::move(clientInfo1));
EXPECT_TRUE(err == OK);
std::shared_ptr<ITranscodingServiceClient> client2 =
@@ -229,7 +224,7 @@
std::make_unique<TranscodingClientManager::ClientInfo>(
client2, kClientId + 1, kClientPid, kClientUid, kClientOpPackageName);
- err = mClientManager->addClient(std::move(clientInfo2));
+ err = mClientManager.addClient(std::move(clientInfo2));
EXPECT_TRUE(err == OK);
std::shared_ptr<ITranscodingServiceClient> client3 =
@@ -240,27 +235,27 @@
std::make_unique<TranscodingClientManager::ClientInfo>(
client3, kClientId + 2, kClientPid, kClientUid, kClientOpPackageName);
- err = mClientManager->addClient(std::move(clientInfo3));
+ err = mClientManager.addClient(std::move(clientInfo3));
EXPECT_TRUE(err == OK);
- size_t numOfClients = mClientManager->getNumOfClients();
+ size_t numOfClients = mClientManager.getNumOfClients();
EXPECT_EQ(numOfClients, 3);
- err = mClientManager->removeClient(kClientId);
+ err = mClientManager.removeClient(kClientId);
EXPECT_TRUE(err == OK);
- err = mClientManager->removeClient(kClientId + 1);
+ err = mClientManager.removeClient(kClientId + 1);
EXPECT_TRUE(err == OK);
- err = mClientManager->removeClient(kClientId + 2);
+ err = mClientManager.removeClient(kClientId + 2);
EXPECT_TRUE(err == OK);
}
TEST_F(TranscodingClientManagerTest, TestRemovingNonExistClient) {
- status_t err = mClientManager->removeClient(kInvalidClientId);
+ status_t err = mClientManager.removeClient(kInvalidClientId);
EXPECT_TRUE(err != OK);
- err = mClientManager->removeClient(1000 /* clientId */);
+ err = mClientManager.removeClient(1000 /* clientId */);
EXPECT_TRUE(err != OK);
}
@@ -272,13 +267,13 @@
std::make_unique<TranscodingClientManager::ClientInfo>(
client, kClientId, kClientPid, kClientUid, kClientOpPackageName);
- status_t err = mClientManager->addClient(std::move(clientInfo));
+ status_t err = mClientManager.addClient(std::move(clientInfo));
EXPECT_TRUE(err == OK);
- bool res = mClientManager->isClientIdRegistered(kClientId);
+ bool res = mClientManager.isClientIdRegistered(kClientId);
EXPECT_TRUE(res);
- res = mClientManager->isClientIdRegistered(kInvalidClientId);
+ res = mClientManager.isClientIdRegistered(kInvalidClientId);
EXPECT_FALSE(res);
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index c88a82a..b29d5f8 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -626,7 +626,8 @@
CHECK(source.get() != NULL);
const char *mime;
- source->getFormat()->findCString(kKeyMIMEType, &mime);
+ sp<MetaData> meta = source->getFormat();
+ meta->findCString(kKeyMIMEType, &mime);
if (Track::getFourCCForMime(mime) == NULL) {
ALOGE("Unsupported mime '%s'", mime);
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 7398690..9fe879e 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -35,10 +35,6 @@
"media_plugin_headers",
],
- export_shared_lib_headers: [
- "libbinder",
- ],
-
cflags: [
"-Wno-multichar",
"-Werror",
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 792a68a..425468f 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -32,7 +32,7 @@
static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
-struct MemorySource : public DataSourceBase {
+struct ID3::MemorySource : public DataSourceBase {
MemorySource(const uint8_t *data, size_t size)
: mData(data),
mSize(size) {
@@ -58,7 +58,7 @@
DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
};
-class DataSourceUnwrapper : public DataSourceBase {
+class ID3::DataSourceUnwrapper : public DataSourceBase {
public:
explicit DataSourceUnwrapper(DataSourceHelper *sourcehelper) {
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 5e433ea..2843a7a 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -77,6 +77,8 @@
size_t rawSize() const { return mRawSize; }
private:
+ class DataSourceUnwrapper;
+ struct MemorySource;
bool mIsValid;
uint8_t *mData;
size_t mSize;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
index 831467a..a5eda26 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -19,6 +19,9 @@
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaFormat;
+
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -65,6 +68,7 @@
private static final int ENCODE_DEFAULT_FRAME_RATE = 25;
private static final int ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
private static final int ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+ private static final int ENCODE_DEFAULT_AUDIO_BIT_RATE = 128000 /* 128 Kbps */;
private String mInputFile;
@Parameterized.Parameters
@@ -107,6 +111,7 @@
int profile = 0;
int level = 0;
int frameRate = 0;
+
//Parameters for audio
int bitRate = 0;
int sampleRate = 0;
@@ -122,6 +127,7 @@
ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+ int colorFormat = COLOR_FormatYUV420Flexible;
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
// Get samples from extractor
@@ -148,6 +154,7 @@
status = decoder.decode(inputBuffer, frameInfo, false, format, "");
assertEquals("Decoder returned error " + status + " for file: " + mInputFile, 0,
status);
+ MediaFormat decoderFormat = decoder.getFormat();
decoder.deInitCodec();
extractor.unselectExtractorTrack(currentTrack);
inputBuffer.clear();
@@ -203,10 +210,17 @@
if (format.containsKey(MediaFormat.KEY_PROFILE)) {
level = format.getInteger(MediaFormat.KEY_LEVEL);
}
+ if (decoderFormat.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
+ colorFormat = decoderFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+ }
} else {
sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
- bitRate = sampleRate * numChannels * 16;
+ if (decoderFormat.containsKey(MediaFormat.KEY_BIT_RATE)) {
+ bitRate = decoderFormat.getInteger(MediaFormat.KEY_BIT_RATE);
+ } else {
+ bitRate = ENCODE_DEFAULT_AUDIO_BIT_RATE;
+ }
}
/*Setup Encode Format*/
MediaFormat encodeFormat;
@@ -219,6 +233,7 @@
encodeFormat.setInteger(MediaFormat.KEY_LEVEL, level);
encodeFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, frameSize);
+ encodeFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
} else {
encodeFormat = MediaFormat.createAudioFormat(mime, sampleRate, numChannels);
encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
@@ -255,7 +270,7 @@
fileInput.close();
}
- @Test
+ @Test(timeout = PER_TEST_TIMEOUT_MS)
public void testNativeEncoder() throws Exception {
File inputFile = new File(mInputFilePath + mInputFile);
assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
@@ -275,8 +290,8 @@
// Encoding the decoder's output
for (String codecName : mediaCodecs) {
Native nativeEncoder = new Native();
- int status = nativeEncoder.Encode(
- mInputFilePath, mInputFile, mDecodedFile, mStatsFile, codecName);
+ int status = nativeEncoder
+ .Encode(mInputFilePath, mInputFile, mDecodedFile, mStatsFile, codecName);
assertEquals(
codecName + " encoder returned error " + status + " for " + "file:" + " " +
mInputFile, 0, status);
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
index 271b852..1277c8b 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeEncoder.cpp
@@ -18,9 +18,9 @@
#define LOG_TAG "NativeEncoder"
#include <jni.h>
+#include <sys/stat.h>
#include <fstream>
#include <iostream>
-#include <sys/stat.h>
#include <android/log.h>
@@ -29,6 +29,11 @@
#include <stdio.h>
+constexpr int32_t ENCODE_DEFAULT_FRAME_RATE = 25;
+constexpr int32_t ENCODE_DEFAULT_AUDIO_BIT_RATE = 128000 /* 128 Kbps */;
+constexpr int32_t ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+constexpr int32_t ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+
extern "C" JNIEXPORT int JNICALL Java_com_android_media_benchmark_library_Native_Encode(
JNIEnv *env, jobject thiz, jstring jFilePath, jstring jFileName, jstring jOutFilePath,
jstring jStatsFile, jstring jCodecName) {
@@ -72,7 +77,7 @@
ALOGE("Track Format invalid");
return -1;
}
- uint8_t *inputBuffer = (uint8_t *) malloc(fileSize);
+ uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
if (!inputBuffer) {
ALOGE("Insufficient memory");
return -1;
@@ -110,6 +115,8 @@
free(inputBuffer);
return -1;
}
+
+ AMediaFormat *decoderFormat = decoder->getFormat();
AMediaFormat *format = extractor->getFormat();
if (inputBuffer) {
free(inputBuffer);
@@ -146,29 +153,34 @@
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &encParams.frameRate);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &encParams.bitrate);
if (encParams.bitrate <= 0 || encParams.frameRate <= 0) {
- encParams.frameRate = 25;
+ encParams.frameRate = ENCODE_DEFAULT_FRAME_RATE;
if (!strcmp(mime, "video/3gpp") || !strcmp(mime, "video/mp4v-es")) {
- encParams.bitrate = 600000 /* 600 Kbps */;
+ encParams.bitrate = ENCODE_MIN_BIT_RATE /* 600 Kbps */;
} else {
- encParams.bitrate = 8000000 /* 8 Mbps */;
+ encParams.bitrate = ENCODE_DEFAULT_BIT_RATE /* 8 Mbps */;
}
}
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_PROFILE, &encParams.profile);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_LEVEL, &encParams.level);
+ AMediaFormat_getInt32(decoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT,
+ &encParams.colorFormat);
} else {
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &encParams.sampleRate);
AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT,
&encParams.numChannels);
- encParams.bitrate =
- encParams.sampleRate * encParams.numChannels * 16 /* bitsPerSample */;
+ encParams.bitrate = ENCODE_DEFAULT_AUDIO_BIT_RATE;
}
Encoder *encoder = new Encoder();
encoder->setupEncoder();
status = encoder->encode(sCodecName, eleStream, eleSize, asyncMode[i], encParams,
- (char *) mime);
+ (char *)mime);
+ if (status != AMEDIA_OK) {
+ ALOGE("Encoder returned error");
+ return -1;
+ }
+ ALOGV("Encoding complete with codec %s for asyncMode = %d", sCodecName.c_str(),
+ asyncMode[i]);
encoder->deInitCodec();
- cout << "codec : " << codecName << endl;
- ALOGV(" asyncMode = %d \n", asyncMode[i]);
const char *statsFile = env->GetStringUTFChars(jStatsFile, nullptr);
encoder->dumpStatistics(sInputReference, extractor->getClipDuration(), sCodecName,
(asyncMode[i] ? "async" : "sync"), statsFile);
@@ -189,6 +201,10 @@
AMediaFormat_delete(format);
format = nullptr;
}
+ if (decoderFormat) {
+ AMediaFormat_delete(decoderFormat);
+ decoderFormat = nullptr;
+ }
decoder->deInitCodec();
decoder->resetDecoder();
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
index 3b1eed4..66fee33 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -134,7 +134,6 @@
mStats.addOutputTime();
onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
if (mSawOutputEOS) {
- Log.i(TAG, "Saw output EOS");
synchronized (mLock) { mLock.notify(); }
}
}
@@ -211,9 +210,6 @@
}
onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
}
- if (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
- Log.i(TAG, "Saw output EOS");
- }
}
}
mInputBuffer.clear();
@@ -256,14 +252,21 @@
*/
public void resetDecoder() { mStats.reset(); }
+ /**
+ * Returns the format of the output buffers
+ */
+ public MediaFormat getFormat() {
+ return mCodec.getOutputFormat();
+ }
+
private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
if ((inputBufferId >= 0) && !mSawInputEOS) {
ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
BufferInfo bufInfo = mInputBufferInfo.get(mIndex);
inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
mIndex++;
- if (bufInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
- mSawInputEOS = true;
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ if (mSawInputEOS) {
Log.i(TAG, "Saw input EOS");
}
mStats.addFrameSize(bufInfo.size);
@@ -301,6 +304,9 @@
}
}
mediaCodec.releaseOutputBuffer(outputBufferId, false);
- mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Saw output EOS");
+ }
}
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
index 40cf8bd..8df462e 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -260,12 +260,12 @@
}
mStats.addFrameSize(outputBuffer.remaining());
mediaCodec.releaseOutputBuffer(outputBufferId, false);
- mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ mSawOutputEOS = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
}
private void onInputAvailable(MediaCodec mediaCodec, int inputBufferId) throws IOException {
- if (mSawOutputEOS || inputBufferId < 0) {
- if (mSawOutputEOS) {
+ if (mSawInputEOS || inputBufferId < 0) {
+ if (mSawInputEOS) {
Log.i(TAG, "Saw input EOS");
}
return;
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
index 2171589..090f3e1 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -63,8 +63,8 @@
ssize_t bytesRead = 0;
uint32_t flag = 0;
int64_t presentationTimeUs = 0;
- tie(bytesRead, flag, presentationTimeUs) = readSampleData(
- mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
+ tie(bytesRead, flag, presentationTimeUs) =
+ readSampleData(mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
if (flag == AMEDIA_ERROR_MALFORMED) {
mErrorCode = (media_status_t)flag;
mSignalledError = true;
@@ -144,6 +144,11 @@
if (!mFormat) mFormat = mExtractor->getFormat();
}
+AMediaFormat *Decoder::getFormat() {
+ ALOGV("In %s", __func__);
+ return AMediaCodec_getOutputFormat(mCodec);
+}
+
int32_t Decoder::decode(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo,
string &codecName, bool asyncMode, FILE *outFp) {
ALOGV("In %s", __func__);
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
index f3fa6a1..e619cb4 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.h
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -57,6 +57,8 @@
void resetDecoder();
+ AMediaFormat *getFormat();
+
// Async callback APIs
void onInputAvailable(AMediaCodec *codec, int32_t index) override;
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
index 2db612c..8dfe993 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -181,8 +181,8 @@
mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
}
-int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize,
- bool asyncMode, encParameter encParams, char *mime) {
+int32_t Encoder::encode(string &codecName, ifstream &eleStream, size_t eleSize, bool asyncMode,
+ encParameter encParams, char *mime) {
ALOGV("In %s", __func__);
mEleStream = &eleStream;
mInputBufferSize = eleSize;
@@ -202,6 +202,7 @@
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_PROFILE, mParams.profile);
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_LEVEL, mParams.level);
}
+ AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, mParams.colorFormat);
} else {
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_SAMPLE_RATE, mParams.sampleRate);
AMediaFormat_setInt32(mFormat, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mParams.numChannels);
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
index 3d12600..5ad142b 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.h
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -23,9 +23,11 @@
#include <queue>
#include <thread>
+#include "media/NdkImage.h"
#include "BenchmarkCommon.h"
#include "Stats.h"
+
struct encParameter {
int32_t bitrate = -1;
int32_t numFrames = -1;
@@ -38,6 +40,7 @@
int32_t frameRate = -1;
int32_t profile = 0;
int32_t level = 0;
+ int32_t colorFormat = AIMAGE_FORMAT_YUV_420_888;
};
class Encoder : public CallBackHandle {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7b14050..ad09680 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6109,6 +6109,7 @@
mHwPaused = false;
mFlushPending = false;
mTimestampVerifier.discontinuity(); // DIRECT and OFFLOADED flush resets frame count.
+ mTimestamp.clear();
}
int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 11660f0..bf1a34f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -353,11 +353,11 @@
// determine if exiting on success (or implicit failure as desc is 0)
if (hasAddrMatch ||
!((hasUsageExcludeRules && usageExclusionFound) ||
- (hasUserIdExcludeRules && userIdExclusionFound) ||
(hasUsageMatchRules && !usageMatchFound) ||
(hasUidExcludeRules && uidExclusionFound) ||
- (hasUidMatchRules && !uidMatchFound)) ||
- (hasUserIdMatchRules && !userIdMatchFound)) {
+ (hasUidMatchRules && !uidMatchFound) ||
+ (hasUserIdExcludeRules && userIdExclusionFound) ||
+ (hasUserIdMatchRules && !userIdMatchFound))) {
ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
return MixMatchStatus::MATCH;
}
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index ee32afe..8bc2837 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1073,11 +1073,6 @@
ALOGV("%s() mAudioPolicyManager == NULL", __func__);
return NO_INIT;
}
- uint_t callingUid = IPCThreadState::self()->getCallingUid();
- if (uid != callingUid) {
- ALOGD("%s() uid invalid %d != %d", __func__, uid, callingUid);
- return PERMISSION_DENIED;
- }
return mAudioPolicyManager->setAllowedCapturePolicy(uid, capturePolicy);
}
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
index 63e293a..2daacd1 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
@@ -66,7 +66,7 @@
}
bool FrameProcessor::processSingleFrame(CaptureResult &frame,
- const sp<CameraDeviceBase> &device) {
+ const sp<FrameProducer> &device) {
sp<Camera2Client> client = mClient.promote();
if (!client.get()) {
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.h b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
index 142b8cd..bb985f6 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
@@ -24,6 +24,7 @@
#include <utils/List.h>
#include <camera/CameraMetadata.h>
+#include "common/CameraDeviceBase.h"
#include "common/FrameProcessorBase.h"
struct camera_frame_metadata;
@@ -54,7 +55,7 @@
void processNewFrames(const sp<Camera2Client> &client);
virtual bool processSingleFrame(CaptureResult &frame,
- const sp<CameraDeviceBase> &device);
+ const sp<FrameProducer> &device);
status_t processFaceDetect(const CameraMetadata &frame,
const sp<Camera2Client> &client);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index ff9d274..e35b436 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -117,8 +117,8 @@
threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
mFrameProcessor->run(threadName.string());
- mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
- FRAME_PROCESSOR_LISTENER_MAX_ID,
+ mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+ camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this,
/*sendPartials*/true);
@@ -526,7 +526,8 @@
// streams are also supported.
std::vector<int> internalStreams;
mCompositeStreamMap.valueAt(i)->insertCompositeStreamIds(&internalStreams);
- std::remove_if(offlineStreamIds->begin(), offlineStreamIds->end(),
+ offlineStreamIds->erase(
+ std::remove_if(offlineStreamIds->begin(), offlineStreamIds->end(),
[&internalStreams] (int streamId) {
auto it = std::find(internalStreams.begin(), internalStreams.end(),
streamId);
@@ -535,8 +536,7 @@
return true;
}
- return false;
- });
+ return false;}), offlineStreamIds->end());
if (internalStreams.empty()) {
offlineStreamIds->push_back(mCompositeStreamMap.valueAt(i)->getStreamId());
}
@@ -818,7 +818,7 @@
}
hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
bool earlyExit = false;
- metadataGetter getMetadata = [this](const String8 &id) {return mDevice->info(id);};
+ metadataGetter getMetadata = [this](const String8 &id) {return mDevice->infoPhysical(id);};
std::vector<std::string> physicalCameraIds;
mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
res = convertToHALStreamCombination(sessionConfiguration, mCameraIdStr,
@@ -1010,7 +1010,7 @@
sp<Surface> surface;
res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
- mCameraIdStr, mDevice->info(physicalCameraId));
+ mCameraIdStr, mDevice->infoPhysical(physicalCameraId));
if (!res.isOk())
return res;
@@ -1314,7 +1314,7 @@
OutputStreamInfo outInfo;
sp<Surface> surface;
res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
- newOutputsMap.valueAt(i), mCameraIdStr, mDevice->info(physicalCameraId));
+ newOutputsMap.valueAt(i), mCameraIdStr, mDevice->infoPhysical(physicalCameraId));
if (!res.isOk())
return res;
@@ -1897,7 +1897,7 @@
sp<Surface> surface;
res = createSurfaceFromGbp(mStreamInfoMap[streamId], true /*isStreamInfoValid*/,
- surface, bufferProducer, mCameraIdStr, mDevice->info(physicalId));
+ surface, bufferProducer, mCameraIdStr, mDevice->infoPhysical(physicalId));
if (!res.isOk())
return res;
@@ -2005,7 +2005,8 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
- std::vector<int32_t> offlineStreamIds(offlineOutputIds.size());
+ std::vector<int32_t> offlineStreamIds;
+ offlineStreamIds.reserve(offlineOutputIds.size());
KeyedVector<sp<IBinder>, sp<CompositeStream>> offlineCompositeStreamMap;
for (const auto& streamId : offlineOutputIds) {
ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
@@ -2206,8 +2207,8 @@
ALOGV("Camera %s: Stopping processors", mCameraIdStr.string());
- mFrameProcessor->removeListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
- FRAME_PROCESSOR_LISTENER_MAX_ID,
+ mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+ camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
/*listener*/this);
mFrameProcessor->requestExit();
ALOGV("Camera %s: Waiting for threads", mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 888fcce..964c96a 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -258,8 +258,6 @@
/** Preview callback related members */
sp<camera2::FrameProcessorBase> mFrameProcessor;
- static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
- static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
std::vector<int32_t> mSupportedPhysicalRequestKeys;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index fc3f137..1edfbf9 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -41,6 +41,16 @@
return NO_INIT;
}
+ String8 threadName;
+ mFrameProcessor = new camera2::FrameProcessorBase(mOfflineSession);
+ threadName = String8::format("Offline-%s-FrameProc", mCameraIdStr.string());
+ mFrameProcessor->run(threadName.string());
+
+ mFrameProcessor->registerListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+ camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
+ /*listener*/this,
+ /*sendPartials*/true);
+
wp<NotificationListener> weakThis(this);
res = mOfflineSession->initialize(weakThis);
if (res != OK) {
@@ -62,7 +72,7 @@
return BasicClient::dump(fd, args);
}
-status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& /*args*/) {
+status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& args) {
String8 result;
result = " Offline session dump:\n";
@@ -74,6 +84,8 @@
return NO_ERROR;
}
+ mFrameProcessor->dump(fd, args);
+
auto res = mOfflineSession->dump(fd);
if (res != OK) {
result = String8::format(" Error dumping offline session: %s (%d)",
@@ -108,6 +120,12 @@
remote->unlinkToDeath(sCameraService);
}
+ mFrameProcessor->removeListener(camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+ camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID,
+ /*listener*/this);
+ mFrameProcessor->requestExit();
+ mFrameProcessor->join();
+
finishCameraOps();
ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
mCameraIdStr.string(), mClientPid);
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 6792039..b67fcb3 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -101,6 +101,8 @@
sp<CameraOfflineSessionBase> mOfflineSession;
+ sp<camera2::FrameProcessorBase> mFrameProcessor;
+
// Offline composite stream map, output surface -> composite stream
KeyedVector<sp<IBinder>, sp<CompositeStream>> mCompositeStreamMap;
};
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 2aa1207..3662a65 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -34,6 +34,7 @@
#include "gui/IGraphicBufferProducer.h"
#include "device3/Camera3StreamInterface.h"
#include "binder/Status.h"
+#include "FrameProducer.h"
#include "CameraOfflineSessionBase.h"
@@ -48,16 +49,11 @@
* Base interface for version >= 2 camera device classes, which interface to
* camera HAL device versions >= 2.
*/
-class CameraDeviceBase : public virtual RefBase {
+class CameraDeviceBase : public virtual FrameProducer {
public:
virtual ~CameraDeviceBase();
/**
- * The device's camera ID
- */
- virtual const String8& getId() const = 0;
-
- /**
* The device vendor tag ID
*/
virtual metadata_vendor_id_t getVendorTagId() const = 0;
@@ -68,13 +64,9 @@
virtual status_t dump(int fd, const Vector<String16> &args) = 0;
/**
- * The device's static characteristics metadata buffer
- */
- virtual const CameraMetadata& info() const = 0;
- /**
* The physical camera device's static characteristics metadata buffer
*/
- virtual const CameraMetadata& info(const String8& physicalId) const = 0;
+ virtual const CameraMetadata& infoPhysical(const String8& physicalId) const = 0;
struct PhysicalCameraSettings {
std::string cameraId;
@@ -278,21 +270,6 @@
virtual bool willNotify3A() = 0;
/**
- * Wait for a new frame to be produced, with timeout in nanoseconds.
- * Returns TIMED_OUT when no frame produced within the specified duration
- * May be called concurrently to most methods, except for getNextFrame
- */
- virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
-
- /**
- * Get next capture result frame from the result queue. Returns NOT_ENOUGH_DATA
- * if the queue is empty; caller takes ownership of the metadata buffer inside
- * the capture result object's metadata field.
- * May be called concurrently to most methods, except for waitForNextFrame.
- */
- virtual status_t getNextResult(CaptureResult *frame) = 0;
-
- /**
* Trigger auto-focus. The latest ID used in a trigger autofocus or cancel
* autofocus call will be returned by the HAL in all subsequent AF
* notifications.
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
index 05ea7fb..1f835a9 100644
--- a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
@@ -22,6 +22,7 @@
#include <utils/Timers.h>
#include "camera/CaptureResult.h"
+#include "FrameProducer.h"
namespace android {
@@ -54,27 +55,17 @@
virtual ~NotificationListener() {}
};
-class CameraOfflineSessionBase : public virtual RefBase {
+class CameraOfflineSessionBase : public virtual FrameProducer {
public:
virtual ~CameraOfflineSessionBase();
virtual status_t initialize(
wp<NotificationListener> listener) = 0;
- // The session's original camera ID
- virtual const String8& getId() const = 0;
-
virtual status_t disconnect() = 0;
virtual status_t dump(int fd) = 0;
- /**
- * Capture result passing
- */
- virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
-
- virtual status_t getNextResult(CaptureResult *frame) = 0;
-
// TODO: notification passing path
}; // class CameraOfflineSessionBase
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
index 3d56cd2..e259379 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
@@ -18,20 +18,21 @@
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
+#include <map>
#include <utils/Log.h>
#include <utils/Trace.h>
+#include "common/FrameProducer.h"
#include "common/FrameProcessorBase.h"
-#include "common/CameraDeviceBase.h"
namespace android {
namespace camera2 {
-FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) :
+FrameProcessorBase::FrameProcessorBase(wp<FrameProducer> device) :
Thread(/*canCallJava*/false),
mDevice(device),
mNumPartialResults(1) {
- sp<CameraDeviceBase> cameraDevice = device.promote();
+ sp<FrameProducer> cameraDevice = device.promote();
if (cameraDevice != 0) {
CameraMetadata staticInfo = cameraDevice->info();
camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
@@ -115,7 +116,7 @@
bool FrameProcessorBase::threadLoop() {
status_t res;
- sp<CameraDeviceBase> device;
+ sp<FrameProducer> device;
{
device = mDevice.promote();
if (device == 0) return false;
@@ -132,7 +133,7 @@
return true;
}
-void FrameProcessorBase::processNewFrames(const sp<CameraDeviceBase> &device) {
+void FrameProcessorBase::processNewFrames(const sp<FrameProducer> &device) {
status_t res;
ATRACE_CALL();
CaptureResult result;
@@ -142,7 +143,7 @@
while ( (res = device->getNextResult(&result)) == OK) {
// TODO: instead of getting frame number from metadata, we should read
- // this from result.mResultExtras when CameraDeviceBase interface is fixed.
+ // this from result.mResultExtras when FrameProducer interface is fixed.
camera_metadata_entry_t entry;
entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
@@ -174,14 +175,14 @@
}
bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
- const sp<CameraDeviceBase> &device) {
+ const sp<FrameProducer> &device) {
ALOGV("%s: Camera %s: Process single frame (is empty? %d)",
__FUNCTION__, device->getId().string(), result.mMetadata.isEmpty());
return processListeners(result, device) == OK;
}
status_t FrameProcessorBase::processListeners(const CaptureResult &result,
- const sp<CameraDeviceBase> &device) {
+ const sp<FrameProducer> &device) {
ATRACE_CALL();
camera_metadata_ro_entry_t entry;
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.h b/services/camera/libcameraservice/common/FrameProcessorBase.h
index ae6d15d..be1ebc6 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.h
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.h
@@ -27,22 +27,25 @@
namespace android {
-class CameraDeviceBase;
+class FrameProducer;
namespace camera2 {
/* Output frame metadata processing thread. This thread waits for new
- * frames from the device, and analyzes them as necessary.
+ * frames from the frame producer, and analyzes them as necessary.
*/
class FrameProcessorBase: public Thread {
public:
- explicit FrameProcessorBase(wp<CameraDeviceBase> device);
+ explicit FrameProcessorBase(wp<FrameProducer> device);
virtual ~FrameProcessorBase();
struct FilteredListener: virtual public RefBase {
virtual void onResultAvailable(const CaptureResult &result) = 0;
};
+ static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0;
+ static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
+
// Register a listener for a range of IDs [minId, maxId). Multiple listeners
// can be listening to the same range. Registering the same listener with
// the same range of IDs has no effect.
@@ -56,7 +59,7 @@
void dump(int fd, const Vector<String16>& args);
protected:
static const nsecs_t kWaitDuration = 10000000; // 10 ms
- wp<CameraDeviceBase> mDevice;
+ wp<FrameProducer> mDevice;
virtual bool threadLoop();
@@ -74,13 +77,13 @@
// Number of partial result the HAL will potentially send.
int32_t mNumPartialResults;
- void processNewFrames(const sp<CameraDeviceBase> &device);
+ void processNewFrames(const sp<FrameProducer> &device);
virtual bool processSingleFrame(CaptureResult &result,
- const sp<CameraDeviceBase> &device);
+ const sp<FrameProducer> &device);
status_t processListeners(const CaptureResult &result,
- const sp<CameraDeviceBase> &device);
+ const sp<FrameProducer> &device);
CameraMetadata mLastFrame;
std::vector<PhysicalCaptureResultInfo> mLastPhysicalFrames;
diff --git a/services/camera/libcameraservice/common/FrameProducer.h b/services/camera/libcameraservice/common/FrameProducer.h
new file mode 100644
index 0000000..a14b3d6
--- /dev/null
+++ b/services/camera/libcameraservice/common/FrameProducer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 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 ANDROID_SERVERS_CAMERA_FRAMEPRODUCER_H
+#define ANDROID_SERVERS_CAMERA_FRAMEPRODUCER_H
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include "camera/CameraMetadata.h"
+#include "camera/CaptureResult.h"
+
+namespace android {
+
+/**
+ * Abstract class for HAL frame producers
+ */
+class FrameProducer : public virtual RefBase {
+ public:
+ /**
+ * Retrieve the static characteristics metadata buffer
+ */
+ virtual const CameraMetadata& info() const = 0;
+
+ /**
+ * Retrieve the device camera ID
+ */
+ virtual const String8& getId() const = 0;
+
+ /**
+ * Wait for a new frame to be produced, with timeout in nanoseconds.
+ * Returns TIMED_OUT when no frame produced within the specified duration
+ * May be called concurrently to most methods, except for getNextFrame
+ */
+ virtual status_t waitForNextFrame(nsecs_t timeout) = 0;
+
+ /**
+ * Get next capture result frame from the result queue. Returns NOT_ENOUGH_DATA
+ * if the queue is empty; caller takes ownership of the metadata buffer inside
+ * the capture result object's metadata field.
+ * May be called concurrently to most methods, except for waitForNextFrame.
+ */
+ virtual status_t getNextResult(CaptureResult *frame) = 0;
+
+}; // class FrameProducer
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d38bfee..90d21a2 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -814,7 +814,7 @@
return OK;
}
-const CameraMetadata& Camera3Device::info(const String8& physicalId) const {
+const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
ALOGVV("%s: E", __FUNCTION__);
if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
mStatus == STATUS_ERROR)) {
@@ -837,7 +837,7 @@
const CameraMetadata& Camera3Device::info() const {
String8 emptyId;
- return info(emptyId);
+ return infoPhysical(emptyId);
}
status_t Camera3Device::checkStatusOkToCaptureLocked() {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0764320..e13e45f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -98,7 +98,7 @@
status_t disconnect() override;
status_t dump(int fd, const Vector<String16> &args) override;
const CameraMetadata& info() const override;
- const CameraMetadata& info(const String8& physicalId) const override;
+ const CameraMetadata& infoPhysical(const String8& physicalId) const override;
// Capture and setStreamingRequest will configure streams if currently in
// idle state
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index 8150de3..5942868 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -167,7 +167,9 @@
streams.push_back(mInputStream);
}
- mSession->close();
+ if (mSession != nullptr) {
+ mSession->close();
+ }
FlushInflightReqStates states {
mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
@@ -461,4 +463,8 @@
return ret;
}
+const CameraMetadata& Camera3OfflineSession::info() const {
+ return mDeviceInfo;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 969220f..27043d2 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -142,13 +142,14 @@
/**
* CameraOfflineSessionBase interface
*/
- const String8& getId() const override;
-
status_t disconnect() override;
-
status_t dump(int fd) override;
- // methods for capture result passing
+ /**
+ * FrameProducer interface
+ */
+ const String8& getId() const override;
+ const CameraMetadata& info() const override;
status_t waitForNextFrame(nsecs_t timeout) override;
status_t getNextResult(CaptureResult *frame) override;
diff --git a/services/camera/libcameraservice/device3/ZoomRatioMapper.h b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
index 16b223b..aa3d913 100644
--- a/services/camera/libcameraservice/device3/ZoomRatioMapper.h
+++ b/services/camera/libcameraservice/device3/ZoomRatioMapper.h
@@ -40,7 +40,8 @@
bool supportNativeZoomRatio, bool usePrecorrectArray);
ZoomRatioMapper(const ZoomRatioMapper& other) :
mHalSupportsZoomRatio(other.mHalSupportsZoomRatio),
- mArrayWidth(other.mArrayWidth), mArrayHeight(other.mArrayHeight) {}
+ mArrayWidth(other.mArrayWidth), mArrayHeight(other.mArrayHeight),
+ mIsValid(other.mIsValid) {}
/**
* Initialize request template with valid zoomRatio if necessary.
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
index 3dc43f1..17347a9 100644
--- a/services/mediatranscoding/Android.bp
+++ b/services/mediatranscoding/Android.bp
@@ -5,8 +5,11 @@
srcs: ["MediaTranscodingService.cpp"],
shared_libs: [
+ "libbase",
"libbinder_ndk",
"liblog",
+ "libmediatranscoding",
+ "libutils",
],
static_libs: [
@@ -27,11 +30,13 @@
],
shared_libs: [
+ "libbase",
// TODO(hkuang): Use libbinder_ndk
"libbinder",
"libutils",
"liblog",
"libbase",
+ "libmediatranscoding",
"libmediatranscodingservice",
],
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index 0269896..82d4161 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -16,16 +16,37 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaTranscodingService"
-#include "MediaTranscodingService.h"
-
+#include <MediaTranscodingService.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <utils/Vector.h>
namespace android {
-MediaTranscodingService::MediaTranscodingService() {
+// Convenience methods for constructing binder::Status objects for error returns
+#define STATUS_ERROR_FMT(errorCode, errorString, ...) \
+ Status::fromServiceSpecificErrorWithMessage( \
+ errorCode, \
+ String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, ##__VA_ARGS__))
+
+// Can MediaTranscoding service trust the caller based on the calling UID?
+// TODO(hkuang): Add MediaProvider's UID.
+static bool isTrustedCallingUid(uid_t uid) {
+ switch (uid) {
+ case AID_ROOT: // root user
+ case AID_SYSTEM:
+ case AID_SHELL:
+ case AID_MEDIA: // mediaserver
+ return true;
+ default:
+ return false;
+ }
+}
+
+MediaTranscodingService::MediaTranscodingService()
+ : mTranscodingClientManager(TranscodingClientManager::getInstance()) {
ALOGV("MediaTranscodingService is created");
}
@@ -33,9 +54,17 @@
ALOGE("Should not be in ~MediaTranscodingService");
}
-binder_status_t MediaTranscodingService::dump(int /* fd */, const char** /*args*/,
- uint32_t /*numArgs*/) {
- // TODO(hkuang): Add implementation.
+binder_status_t MediaTranscodingService::dump(int fd, const char** /*args*/, uint32_t /*numArgs*/) {
+ String8 result;
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "MediaTranscodingService: %p\n", this);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+
+ Vector<String16> args;
+ mTranscodingClientManager.dumpAllClients(fd, args);
return OK;
}
@@ -51,15 +80,97 @@
}
Status MediaTranscodingService::registerClient(
- const std::shared_ptr<ITranscodingServiceClient>& /*in_client*/,
- const std::string& /* in_opPackageName */, int32_t /* in_clientUid */,
- int32_t /* in_clientPid */, int32_t* /*_aidl_return*/) {
- // TODO(hkuang): Add implementation.
+ const std::shared_ptr<ITranscodingServiceClient>& in_client,
+ const std::string& in_opPackageName, int32_t in_clientUid, int32_t in_clientPid,
+ int32_t* _aidl_return) {
+ if (in_client == nullptr) {
+ ALOGE("Client can not be null");
+ *_aidl_return = kInvalidJobId;
+ return Status::fromServiceSpecificError(ERROR_ILLEGAL_ARGUMENT);
+ }
+
+ int32_t callingPid = AIBinder_getCallingPid();
+ int32_t callingUid = AIBinder_getCallingUid();
+
+ // Check if we can trust clientUid. Only privilege caller could forward the uid on app client's behalf.
+ if (in_clientUid == USE_CALLING_UID) {
+ in_clientUid = callingUid;
+ } else if (!isTrustedCallingUid(callingUid)) {
+ ALOGE("MediaTranscodingService::registerClient failed (calling PID %d, calling UID %d) "
+ "rejected "
+ "(don't trust clientUid %d)",
+ in_clientPid, in_clientUid, in_clientUid);
+ return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+ "Untrusted caller (calling PID %d, UID %d) trying to "
+ "register client",
+ in_clientPid, in_clientUid);
+ }
+
+ // Check if we can trust clientPid. Only privilege caller could forward the pid on app client's behalf.
+ if (in_clientPid == USE_CALLING_PID) {
+ in_clientPid = callingPid;
+ } else if (!isTrustedCallingUid(callingUid)) {
+ ALOGE("MediaTranscodingService::registerClient client failed (calling PID %d, calling UID "
+ "%d) rejected "
+ "(don't trust clientPid %d)",
+ in_clientPid, in_clientUid, in_clientPid);
+ return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+ "Untrusted caller (calling PID %d, UID %d) trying to "
+ "register client",
+ in_clientPid, in_clientUid);
+ }
+
+ // We know the clientId must be equal to its pid as we assigned client's pid as its clientId.
+ int32_t clientId = in_clientPid;
+
+ // Checks if the client already registers.
+ if (mTranscodingClientManager.isClientIdRegistered(clientId)) {
+ return Status::fromServiceSpecificError(ERROR_ALREADY_EXISTS);
+ }
+
+ // Creates the client and uses its process id as client id.
+ std::unique_ptr<TranscodingClientManager::ClientInfo> newClient =
+ std::make_unique<TranscodingClientManager::ClientInfo>(
+ in_client, clientId, in_clientPid, in_clientUid, in_opPackageName);
+ status_t err = mTranscodingClientManager.addClient(std::move(newClient));
+ if (err != OK) {
+ *_aidl_return = kInvalidClientId;
+ return STATUS_ERROR_FMT(err, "Failed to add client to TranscodingClientManager");
+ }
+
+ ALOGD("Assign client: %s pid: %d, uid: %d with id: %d", in_opPackageName.c_str(), in_clientPid,
+ in_clientUid, clientId);
+
+ *_aidl_return = clientId;
return Status::ok();
}
-Status MediaTranscodingService::unregisterClient(int32_t /*clientId*/, bool* /*_aidl_return*/) {
- // TODO(hkuang): Add implementation.
+Status MediaTranscodingService::unregisterClient(int32_t clientId, bool* _aidl_return) {
+ ALOGD("unregisterClient id: %d", clientId);
+ int32_t callingUid = AIBinder_getCallingUid();
+ int32_t callingPid = AIBinder_getCallingPid();
+
+ // Only the client with clientId or the trusted caller could unregister the client.
+ if (callingPid != clientId) {
+ if (!isTrustedCallingUid(callingUid)) {
+ ALOGE("Untrusted caller (calling PID %d, UID %d) trying to "
+ "unregister client with id: %d",
+ callingUid, callingPid, clientId);
+ *_aidl_return = true;
+ return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+ "Untrusted caller (calling PID %d, UID %d) trying to "
+ "unregister client with id: %d",
+ callingUid, callingPid, clientId);
+ }
+ }
+
+ *_aidl_return = (mTranscodingClientManager.removeClient(clientId) == OK);
+ return Status::ok();
+}
+
+Status MediaTranscodingService::getNumOfClients(int32_t* _aidl_return) {
+ ALOGD("MediaTranscodingService::getNumOfClients");
+ *_aidl_return = mTranscodingClientManager.getNumOfClients();
return Status::ok();
}
diff --git a/services/mediatranscoding/MediaTranscodingService.h b/services/mediatranscoding/MediaTranscodingService.h
index d225f9a..cc69727 100644
--- a/services/mediatranscoding/MediaTranscodingService.h
+++ b/services/mediatranscoding/MediaTranscodingService.h
@@ -19,6 +19,7 @@
#include <aidl/android/media/BnMediaTranscodingService.h>
#include <binder/IServiceManager.h>
+#include <media/TranscodingClientManager.h>
namespace android {
@@ -30,6 +31,9 @@
class MediaTranscodingService : public BnMediaTranscodingService {
public:
+ static constexpr int32_t kInvalidJobId = -1;
+ static constexpr int32_t kInvalidClientId = -1;
+
MediaTranscodingService();
virtual ~MediaTranscodingService();
@@ -43,6 +47,8 @@
Status unregisterClient(int32_t clientId, bool* _aidl_return) override;
+ Status getNumOfClients(int32_t* _aidl_return) override;
+
Status submitRequest(int32_t in_clientId, const TranscodingRequestParcel& in_request,
TranscodingJobParcel* out_job, int32_t* _aidl_return) override;
@@ -54,6 +60,11 @@
virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
private:
+ friend class MediaTranscodingServiceTest;
+
+ mutable std::mutex mServiceLock;
+
+ TranscodingClientManager& mTranscodingClientManager;
};
} // namespace android
diff --git a/services/mediatranscoding/tests/Android.bp b/services/mediatranscoding/tests/Android.bp
new file mode 100644
index 0000000..e0e040c
--- /dev/null
+++ b/services/mediatranscoding/tests/Android.bp
@@ -0,0 +1,35 @@
+// Build the unit tests for MediaTranscodingService
+
+cc_defaults {
+ name: "mediatranscodingservice_test_defaults",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+
+ include_dirs: [
+ "frameworks/av/services/mediatranscoding",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libmediatranscodingservice",
+ ],
+
+ static_libs: [
+ "mediatranscoding_aidl_interface-ndk_platform",
+ ],
+}
+
+// MediaTranscodingService unit test
+cc_test {
+ name: "mediatranscodingservice_tests",
+ defaults: ["mediatranscodingservice_test_defaults"],
+
+ srcs: ["mediatranscodingservice_tests.cpp"],
+}
\ No newline at end of file
diff --git a/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh b/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
new file mode 100644
index 0000000..bcdc7f7
--- /dev/null
+++ b/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# Run tests in this directory.
+#
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ echo "Android build environment not set"
+ exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+mm
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount && adb sync
+
+echo "========================================"
+
+echo "testing mediatranscodingservice"
+adb shell /data/nativetest64/mediatranscodingservice_tests/mediatranscodingservice_tests
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp b/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
new file mode 100644
index 0000000..5a791fe
--- /dev/null
+++ b/services/mediatranscoding/tests/mediatranscodingservice_tests.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Unit Test for MediaTranscoding Service.
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaTranscodingServiceTest"
+
+#include <aidl/android/media/BnTranscodingServiceClient.h>
+#include <aidl/android/media/IMediaTranscodingService.h>
+#include <aidl/android/media/ITranscodingServiceClient.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <android/binder_ibinder_jni.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <cutils/ashmem.h>
+#include <gtest/gtest.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+
+namespace android {
+
+namespace media {
+
+using Status = ::ndk::ScopedAStatus;
+using aidl::android::media::BnTranscodingServiceClient;
+using aidl::android::media::IMediaTranscodingService;
+using aidl::android::media::ITranscodingServiceClient;
+
+constexpr int32_t kInvalidClientId = -5;
+
+// Note that -1 is valid and means using calling pid/uid for the service. But only privilege caller could
+// use them. This test is not a privilege caller.
+constexpr int32_t kInvalidClientPid = -5;
+constexpr int32_t kInvalidClientUid = -5;
+constexpr const char* kInvalidClientOpPackageName = "";
+
+constexpr int32_t kClientUseCallingPid = -1;
+constexpr int32_t kClientUseCallingUid = -1;
+constexpr const char* kClientOpPackageName = "TestClient";
+
+class MediaTranscodingServiceTest : public ::testing::Test {
+public:
+ MediaTranscodingServiceTest() { ALOGD("MediaTranscodingServiceTest created"); }
+
+ void SetUp() override {
+ ::ndk::SpAIBinder binder(AServiceManager_getService("media.transcoding"));
+ mService = IMediaTranscodingService::fromBinder(binder);
+ if (mService == nullptr) {
+ ALOGE("Failed to connect to the media.trascoding service.");
+ return;
+ }
+ }
+
+ ~MediaTranscodingServiceTest() { ALOGD("MediaTranscodingingServiceTest destroyed"); }
+
+ std::shared_ptr<IMediaTranscodingService> mService = nullptr;
+};
+
+struct TestClient : public BnTranscodingServiceClient {
+ TestClient(const std::shared_ptr<IMediaTranscodingService>& service) : mService(service) {
+ ALOGD("TestClient Created");
+ }
+
+ Status getName(std::string* _aidl_return) override {
+ *_aidl_return = "test_client";
+ return Status::ok();
+ }
+
+ Status onTranscodingFinished(
+ int32_t /* in_jobId */,
+ const ::aidl::android::media::TranscodingResultParcel& /* in_result */) override {
+ return Status::ok();
+ }
+
+ Status onTranscodingFailed(
+ int32_t /* in_jobId */,
+ ::aidl::android::media::TranscodingErrorCode /*in_errorCode */) override {
+ return Status::ok();
+ }
+
+ Status onAwaitNumberOfJobsChanged(int32_t /* in_jobId */, int32_t /* in_oldAwaitNumber */,
+ int32_t /* in_newAwaitNumber */) override {
+ return Status::ok();
+ }
+
+ Status onProgressUpdate(int32_t /* in_jobId */, int32_t /* in_progress */) override {
+ return Status::ok();
+ }
+
+ virtual ~TestClient() { ALOGI("TestClient destroyed"); };
+
+private:
+ std::shared_ptr<IMediaTranscodingService> mService;
+};
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterNullClient) {
+ std::shared_ptr<ITranscodingServiceClient> client = nullptr;
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+ kClientUseCallingPid, &clientId);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPid) {
+ std::shared_ptr<ITranscodingServiceClient> client =
+ ::ndk::SharedRefBase::make<TestClient>(mService);
+ EXPECT_TRUE(client != nullptr);
+
+ // Register the client with the service.
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+ kInvalidClientPid, &clientId);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientUid) {
+ std::shared_ptr<ITranscodingServiceClient> client =
+ ::ndk::SharedRefBase::make<TestClient>(mService);
+ EXPECT_TRUE(client != nullptr);
+
+ // Register the client with the service.
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kClientOpPackageName, kInvalidClientUid,
+ kClientUseCallingPid, &clientId);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientWithInvalidClientPackageName) {
+ std::shared_ptr<ITranscodingServiceClient> client =
+ ::ndk::SharedRefBase::make<TestClient>(mService);
+ EXPECT_TRUE(client != nullptr);
+
+ // Register the client with the service.
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kInvalidClientOpPackageName,
+ kClientUseCallingUid, kClientUseCallingPid, &clientId);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterOneClient) {
+ std::shared_ptr<ITranscodingServiceClient> client =
+ ::ndk::SharedRefBase::make<TestClient>(mService);
+ EXPECT_TRUE(client != nullptr);
+
+ // Register the client with the service.
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingPid,
+ kClientUseCallingUid, &clientId);
+ ALOGD("client id is %d", clientId);
+ EXPECT_TRUE(status.isOk());
+
+ // Validate the clientId.
+ EXPECT_TRUE(clientId > 0);
+
+ // Check the number of Clients.
+ int32_t numOfClients;
+ status = mService->getNumOfClients(&numOfClients);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_EQ(1, numOfClients);
+
+ // Unregister the client.
+ bool res;
+ status = mService->unregisterClient(clientId, &res);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_TRUE(res);
+}
+
+TEST_F(MediaTranscodingServiceTest, TestUnRegisterClientWithInvalidClientId) {
+ std::shared_ptr<ITranscodingServiceClient> client =
+ ::ndk::SharedRefBase::make<TestClient>(mService);
+ EXPECT_TRUE(client != nullptr);
+
+ // Register the client with the service.
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+ kClientUseCallingPid, &clientId);
+ ALOGD("client id is %d", clientId);
+ EXPECT_TRUE(status.isOk());
+
+ // Validate the clientId.
+ EXPECT_TRUE(clientId > 0);
+
+ // Check the number of Clients.
+ int32_t numOfClients;
+ status = mService->getNumOfClients(&numOfClients);
+ EXPECT_TRUE(status.isOk());
+ EXPECT_EQ(1, numOfClients);
+
+ // Unregister the client with invalid ID
+ bool res;
+ mService->unregisterClient(kInvalidClientId, &res);
+ EXPECT_FALSE(res);
+
+ // Unregister the valid client.
+ mService->unregisterClient(clientId, &res);
+}
+
+TEST_F(MediaTranscodingServiceTest, TestRegisterClientTwice) {
+ std::shared_ptr<ITranscodingServiceClient> client =
+ ::ndk::SharedRefBase::make<TestClient>(mService);
+ EXPECT_TRUE(client != nullptr);
+
+ // Register the client with the service.
+ int32_t clientId = 0;
+ Status status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+ kClientUseCallingPid, &clientId);
+ EXPECT_TRUE(status.isOk());
+
+ // Validate the clientId.
+ EXPECT_TRUE(clientId > 0);
+
+ // Register the client again and expects failure.
+ status = mService->registerClient(client, kClientOpPackageName, kClientUseCallingUid,
+ kClientUseCallingPid, &clientId);
+ EXPECT_FALSE(status.isOk());
+
+ // Unregister the valid client.
+ bool res;
+ mService->unregisterClient(clientId, &res);
+}
+
+} // namespace media
+} // namespace android