Files
android_vendor_qcom_opensou…/libqservice/IQService.cpp
Saurabh Shah 86c1729e75 libqservice: Add a client interface.
Add a client interface which interfaces with hwc.
qservice upon receiving IPC, provides a callback notification to the qclient
which does appropriate stuff in hwc.

In future, qservice can safely be even made a separate process with no changes
to exisiting code. This was not true earlier owing to the hwc pointer held by
qservice forcing it to be in the same process that hwc is in.

CRs-fixed: 452977
Change-Id: I05838c213f5d4606a6573693de1bacbc5876107e
2013-02-14 17:27:55 -08:00

143 lines
4.6 KiB
C++

/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are
* retained for attribution purposes only.
* 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.
*/
#include <fcntl.h>
#include <stdint.h>
#include <sys/types.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <utils/Errors.h>
#include <private/android_filesystem_config.h>
#include <IQService.h>
using namespace android;
using namespace qClient;
// ---------------------------------------------------------------------------
namespace qService {
class BpQService : public BpInterface<IQService>
{
public:
BpQService(const sp<IBinder>& impl)
: BpInterface<IQService>(impl) {}
virtual void securing(uint32_t startEnd) {
Parcel data, reply;
data.writeInterfaceToken(IQService::getInterfaceDescriptor());
data.writeInt32(startEnd);
remote()->transact(SECURING, data, &reply);
}
virtual void unsecuring(uint32_t startEnd) {
Parcel data, reply;
data.writeInterfaceToken(IQService::getInterfaceDescriptor());
data.writeInt32(startEnd);
remote()->transact(UNSECURING, data, &reply);
}
virtual void connect(const sp<IQClient>& client) {
Parcel data, reply;
data.writeInterfaceToken(IQService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
remote()->transact(CONNECT, data, &reply);
}
};
IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
// ----------------------------------------------------------------------
static void getProcName(int pid, char *buf, int size);
status_t BnQService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// IPC should be from mediaserver only
IPCThreadState* ipc = IPCThreadState::self();
const int callerPid = ipc->getCallingPid();
const int callerUid = ipc->getCallingUid();
const size_t MAX_BUF_SIZE = 1024;
char callingProcName[MAX_BUF_SIZE] = {0};
getProcName(callerPid, callingProcName, MAX_BUF_SIZE);
const bool permission = (callerUid == AID_MEDIA);
switch(code) {
case SECURING: {
if(!permission) {
ALOGE("display.qservice SECURING access denied: pid=%d uid=%d process=%s",
callerPid, callerUid, callingProcName);
return PERMISSION_DENIED;
}
CHECK_INTERFACE(IQService, data, reply);
uint32_t startEnd = data.readInt32();
securing(startEnd);
return NO_ERROR;
} break;
case UNSECURING: {
if(!permission) {
ALOGE("display.qservice UNSECURING access denied: pid=%d uid=%d process=%s",
callerPid, callerUid, callingProcName);
return PERMISSION_DENIED;
}
CHECK_INTERFACE(IQService, data, reply);
uint32_t startEnd = data.readInt32();
unsecuring(startEnd);
return NO_ERROR;
} break;
case CONNECT: {
CHECK_INTERFACE(IQService, data, reply);
if(callerUid != AID_GRAPHICS) {
ALOGE("display.qservice CONNECT access denied: pid=%d uid=%d process=%s",
callerPid, callerUid, callingProcName);
return PERMISSION_DENIED;
}
sp<IQClient> client =
interface_cast<IQClient>(data.readStrongBinder());
connect(client);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
//Helper
static void getProcName(int pid, char *buf, int size) {
int fd = -1;
snprintf(buf, size, "/proc/%d/cmdline", pid);
fd = open(buf, O_RDONLY);
if (fd < 0) {
strcpy(buf, "Unknown");
} else {
int len = read(fd, buf, size - 1);
buf[len] = 0;
close(fd);
}
}
}; // namespace qService