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 
33 using namespace android;
34 using namespace qClient;
35 
36 // ---------------------------------------------------------------------------
37 
38 namespace qService {
39 
40 class BpQService : public BpInterface<IQService>
41 {
42 public:
BpQService(const sp<IBinder> & impl)43     BpQService(const sp<IBinder>& impl)
44         : BpInterface<IQService>(impl) {}
45 
securing(uint32_t startEnd)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 
unsecuring(uint32_t startEnd)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 
connect(const sp<IQClient> & client)60     virtual void connect(const sp<IQClient>& client) {
61         Parcel data, reply;
62         data.writeInterfaceToken(IQService::getInterfaceDescriptor());
63         data.writeStrongBinder(IInterface::asBinder(client));
64         remote()->transact(CONNECT, data, &reply);
65     }
66 
screenRefresh()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 
76 IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
77 
78 // ----------------------------------------------------------------------
79 
80 static void getProcName(int pid, char *buf, int size);
81 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)82 status_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
getProcName(int pid,char * buf,int size)150 static 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