Home | History | Annotate | Download | only in libqservice
      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:
     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 
     76 IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
     77 
     78 // ----------------------------------------------------------------------
     79 
     80 static void getProcName(int pid, char *buf, int size);
     81 
     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
    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