blob: e95dee500da8497d2b3ba90f58266abae4c41bee [file] [log] [blame]
/*
* 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.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "ECOService"
#include "eco/ECOService.h"
#include <binder/BinderService.h>
#include <cutils/atomic.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <algorithm>
#include <climits>
#include <cstring>
#include <ctime>
#include <string>
#include "eco/ECODebug.h"
namespace android {
namespace media {
namespace eco {
ECOService::ECOService() : BnECOService() {
ALOGD("ECOService created");
updateLogLevel();
}
/*virtual*/ ::android::binder::Status ECOService::obtainSession(
int32_t width, int32_t height, bool isCameraRecording,
::android::sp<::android::media::eco::IECOSession>* _aidl_return) {
ECOLOGI("ECOService::obtainSession w: %d, h: %d, isCameraRecording: %d", width, height,
isCameraRecording);
bool disable = property_get_bool(kDisableEcoServiceProperty, false);
if (disable) {
ECOLOGE("ECOService:: Failed to obtainSession as ECOService is disable");
return STATUS_ERROR(ERROR_UNSUPPORTED, "ECOService is disable");
}
if (width <= 0) {
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Width can not be <= 0");
}
if (height <= 0) {
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Height can not be <= 0");
}
SessionConfig newCfg(width, height, isCameraRecording);
ECOLOGD("session count before is %zu", mSessionConfigToSessionMap.size());
Mutex::Autolock lock(mServiceLock);
bool foundSession = false;
// Instead of looking up the map directly, take the chance to scan the map and evict all the
// invalid sessions.
SanitizeSession([&](MapIterType iter) {
if (iter->first == newCfg) {
sp<ECOSession> session = iter->second.promote();
foundSession = true;
*_aidl_return = session;
}
});
if (foundSession) {
return binder::Status::ok();
}
// Create a new session and add it to the record.
sp<ECOSession> newSession = ECOSession::createECOSession(width, height, isCameraRecording);
if (newSession == nullptr) {
ECOLOGE("ECOService failed to create ECOSession w: %d, h: %d, isCameraRecording: %d", width,
height, isCameraRecording);
return STATUS_ERROR(ERROR_UNSUPPORTED, "Failed to create eco session");
}
*_aidl_return = newSession;
// Insert the new session into the map.
mSessionConfigToSessionMap[newCfg] = newSession;
ECOLOGD("session count after is %zu", mSessionConfigToSessionMap.size());
return binder::Status::ok();
}
/*virtual*/ ::android::binder::Status ECOService::getNumOfSessions(int32_t* _aidl_return) {
Mutex::Autolock lock(mServiceLock);
SanitizeSession(std::function<void(MapIterType it)>()); // empty callback
*_aidl_return = mSessionConfigToSessionMap.size();
return binder::Status::ok();
}
/*virtual*/ ::android::binder::Status ECOService::getSessions(
::std::vector<::android::sp<::android::IBinder>>* _aidl_return) {
// Clear all the entries in the vector.
_aidl_return->clear();
Mutex::Autolock lock(mServiceLock);
SanitizeSession([&](MapIterType iter) {
sp<ECOSession> session = iter->second.promote();
_aidl_return->push_back(IInterface::asBinder(session));
});
return binder::Status::ok();
}
inline bool isEmptySession(const android::wp<ECOSession>& entry) {
sp<ECOSession> session = entry.promote();
return session == nullptr;
}
void ECOService::SanitizeSession(
const std::function<void(std::unordered_map<SessionConfig, wp<ECOSession>,
SessionConfigHash>::iterator it)>& callback) {
for (auto it = mSessionConfigToSessionMap.begin(), end = mSessionConfigToSessionMap.end();
it != end;) {
if (isEmptySession(it->second)) {
it = mSessionConfigToSessionMap.erase(it);
} else {
if (callback != nullptr) {
callback(it);
};
it++;
}
}
}
/*virtual*/ void ECOService::binderDied(const wp<IBinder>& /*who*/) {}
status_t ECOService::dump(int fd, const Vector<String16>& args) {
Mutex::Autolock lock(mServiceLock);
dprintf(fd, "\n== ECO Service info: ==\n\n");
dprintf(fd, "Number of ECOServices: %zu\n", mSessionConfigToSessionMap.size());
for (auto it = mSessionConfigToSessionMap.begin(), end = mSessionConfigToSessionMap.end();
it != end; it++) {
sp<ECOSession> session = it->second.promote();
if (session != nullptr) {
session->dump(fd, args);
}
}
return NO_ERROR;
}
} // namespace eco
} // namespace media
} // namespace android