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