1d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin/* 2d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * Copyright (C) 2010 The Android Open Source Project 31c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed * Copyright (C) 2012-2016, The Linux Foundation. All rights reserved. 4d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * 5d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * Not a Contribution, Apache license notifications and license are 6d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * retained for attribution purposes only. 7d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 8d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * Licensed under the Apache License, Version 2.0 (the "License"); 9d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * you may not use this file except in compliance with the License. 10d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * You may obtain a copy of the License at 11d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * 12d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * http://www.apache.org/licenses/LICENSE-2.0 13d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * 14d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * Unless required by applicable law or agreed to in writing, software 15d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * distributed under the License is distributed on an "AS IS" BASIS, 16d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * See the License for the specific language governing permissions and 18d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin * limitations under the License. 19d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin */ 20d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 21d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <fcntl.h> 22d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <stdint.h> 23d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <sys/types.h> 24d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <binder/Parcel.h> 25d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <binder/IBinder.h> 26d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <binder/IInterface.h> 27d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <binder/IPCThreadState.h> 28d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <utils/Errors.h> 29d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <private/android_filesystem_config.h> 30d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <IQService.h> 31d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 32d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#define QSERVICE_DEBUG 0 33d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 34d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinusing namespace android; 35d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinusing namespace qClient; 36d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 37d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin// --------------------------------------------------------------------------- 38d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 39d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinnamespace qService { 40d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 41d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinclass BpQService : public BpInterface<IQService> 42d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin{ 43d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinpublic: 44d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin BpQService(const sp<IBinder>& impl) 45d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin : BpInterface<IQService>(impl) {} 46d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 47d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin virtual void connect(const sp<IQClient>& client) { 48d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGD_IF(QSERVICE_DEBUG, "%s: connect HWC client", __FUNCTION__); 49d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin Parcel data, reply; 50d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin data.writeInterfaceToken(IQService::getInterfaceDescriptor()); 51d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin data.writeStrongBinder(IInterface::asBinder(client)); 52d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin remote()->transact(CONNECT_HWC_CLIENT, data, &reply); 53d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 54d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 55d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin virtual void connect(const sp<IQHDMIClient>& client) { 56d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGD_IF(QSERVICE_DEBUG, "%s: connect HDMI client", __FUNCTION__); 57d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin Parcel data, reply; 58d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin data.writeInterfaceToken(IQService::getInterfaceDescriptor()); 59d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin data.writeStrongBinder(IInterface::asBinder(client)); 60d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin remote()->transact(CONNECT_HDMI_CLIENT, data, &reply); 61d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 62d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 63d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 64d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel, 65d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin Parcel* outParcel) { 66d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel); 67d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin status_t err = (status_t) android::FAILED_TRANSACTION; 68d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin Parcel data; 69d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin Parcel *reply = outParcel; 70d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin data.writeInterfaceToken(IQService::getInterfaceDescriptor()); 71d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if (inParcel && inParcel->dataSize() > 0) 72d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin data.appendFrom(inParcel, 0, inParcel->dataSize()); 73d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin err = remote()->transact(command, data, reply); 74d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return err; 75d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 76d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}; 77d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 78d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinIMPLEMENT_META_INTERFACE(QService, "android.display.IQService"); 79d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 80d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin// ---------------------------------------------------------------------- 81d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 82d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinstatic void getProcName(int pid, char *buf, int size); 83d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 84d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinstatus_t BnQService::onTransact( 85d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 86d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin{ 87d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGD_IF(QSERVICE_DEBUG, "%s: code: %d", __FUNCTION__, code); 88d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin // IPC should be from certain processes only 89d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin IPCThreadState* ipc = IPCThreadState::self(); 90d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin const int callerPid = ipc->getCallingPid(); 91d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin const int callerUid = ipc->getCallingUid(); 92d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin const int MAX_BUF_SIZE = 1024; 93d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin char callingProcName[MAX_BUF_SIZE] = {0}; 94d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 95d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin getProcName(callerPid, callingProcName, MAX_BUF_SIZE); 96d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 97d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin const bool permission = (callerUid == AID_MEDIA || 98d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin callerUid == AID_GRAPHICS || 99d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin callerUid == AID_ROOT || 1001c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed callerUid == AID_CAMERASERVER || 101d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin callerUid == AID_SYSTEM); 102d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 103d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if (code == CONNECT_HWC_CLIENT) { 104d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin CHECK_INTERFACE(IQService, data, reply); 105d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if(callerUid != AID_GRAPHICS) { 106d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGE("display.qservice CONNECT_HWC_CLIENT access denied: \ 107d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin pid=%d uid=%d process=%s", 108d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin callerPid, callerUid, callingProcName); 109d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return PERMISSION_DENIED; 110d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 111d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin sp<IQClient> client = 112d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin interface_cast<IQClient>(data.readStrongBinder()); 113d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin connect(client); 114d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return NO_ERROR; 115d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } else if(code == CONNECT_HDMI_CLIENT) { 116d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin CHECK_INTERFACE(IQService, data, reply); 117d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if(callerUid != AID_SYSTEM && callerUid != AID_ROOT) { 118d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGE("display.qservice CONNECT_HDMI_CLIENT access denied: \ 119d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin pid=%d uid=%d process=%s", 120d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin callerPid, callerUid, callingProcName); 121d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return PERMISSION_DENIED; 122d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 123d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin sp<IQHDMIClient> client = 124d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin interface_cast<IQHDMIClient>(data.readStrongBinder()); 125d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin connect(client); 126d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return NO_ERROR; 127d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } else if (code > COMMAND_LIST_START && code < COMMAND_LIST_END) { 128d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if(!permission) { 129d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ALOGE("display.qservice access denied: command=%d\ 130d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin pid=%d uid=%d process=%s", code, callerPid, 131d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin callerUid, callingProcName); 132d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return PERMISSION_DENIED; 133d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 134d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin CHECK_INTERFACE(IQService, data, reply); 135d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin dispatch(code, &data, reply); 136d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return NO_ERROR; 137d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } else { 138d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin return BBinder::onTransact(code, data, reply, flags); 139d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 140d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin} 141d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 142d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin//Helper 143d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinstatic void getProcName(int pid, char *buf, int size) { 144d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin int fd = -1; 145d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin snprintf(buf, size, "/proc/%d/cmdline", pid); 146d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin fd = open(buf, O_RDONLY); 147d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if (fd < 0) { 148d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin strlcpy(buf, "Unknown", size); 149d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } else { 150d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin ssize_t len = read(fd, buf, size - 1); 151d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin if (len >= 0) 152d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin buf[len] = 0; 153d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 154d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin close(fd); 155d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin } 156d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin} 157d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin 158d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}; // namespace qService 159