C++程序  |  129行  |  4.25 KB

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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.
 */

#define LOG_TAG "VehicleMonitor"

#include <binder/IPCThreadState.h>
#include <binder/Status.h>
#include <private/android_filesystem_config.h>

#include <utils/Log.h>

#include <IVehicleMonitor.h>

namespace android {
enum {
    SET_APP_PRIORITY = IBinder::FIRST_CALL_TRANSACTION,
    SET_MONITOR_LISTENER,
};

const char IVehicleMonitor::SERVICE_NAME[] = "com.android.car.vehiclemonitor.IVehicleMonitor";

// ----------------------------------------------------------------------------

class BpVehicleMonitor : public BpInterface<IVehicleMonitor> {
public:
    explicit BpVehicleMonitor(const sp<IBinder> & impl)
            : BpInterface<IVehicleMonitor>(impl) {
    }

    virtual status_t setAppPriority(
            uint32_t pid, uint32_t uid, vehicle_app_priority priority) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleMonitor::getInterfaceDescriptor());
        data.writeInt32(1);
        data.writeInt32(pid);
        data.writeInt32(uid);
        data.writeInt32(priority);
        status_t status = remote()->transact(SET_APP_PRIORITY, data, &reply);
        if (status == NO_ERROR) {
            int32_t exceptionCode = reply.readExceptionCode();
            if (exceptionCode != NO_ERROR) {
                if (exceptionCode == binder::Status::EX_SERVICE_SPECIFIC) {
                    return -EAGAIN;
                } else if (exceptionCode == binder::Status::EX_ILLEGAL_STATE) {
                    return -ESHUTDOWN;
                }
                return exceptionCode;
            }
        }
        return status;
    }

    virtual status_t setMonitorListener(
            const sp<IVehicleMonitorListener> &listener) {
        Parcel data, reply;
        data.writeInterfaceToken(IVehicleMonitor::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
        status_t status = remote()->transact(SET_MONITOR_LISTENER, data, &reply);
        return status;
    }
};

IMPLEMENT_META_INTERFACE(VehicleMonitor, IVehicleMonitor::SERVICE_NAME);

// ----------------------------------------------------------------------

static bool isSystemUser() {
    uid_t uid =  IPCThreadState::self()->getCallingUid();
    switch (uid) {
        // This list will be expanded. Only these UIDs are allowed to access vehicle monitor.
        case AID_ROOT:
        case AID_SYSTEM: {
            return true;
        } break;
        default: {
            ALOGE("non-system user tried access, uid %d", uid);
        } break;
    }
    return false;
}

status_t BnVehicleMonitor::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
        uint32_t flags) {
    if (!isSystemUser()) {
        return PERMISSION_DENIED;
    }
    status_t r;
    switch (code) {
        case SET_APP_PRIORITY: {
            CHECK_INTERFACE(IVehicleMonitor, data, reply);
            if (data.readInt32() == 0) { // no data
                ALOGE("null data");
                return BAD_VALUE;
            }
            int32_t pid = data.readInt32();
            int32_t uid = data.readInt32();
            int32_t priority = data.readInt32();
            r = setAppPriority(pid, uid, (vehicle_app_priority) priority);
            reply->writeNoException();
            return r;
        } break;
        case SET_MONITOR_LISTENER: {
            CHECK_INTERFACE(IVehicleMonitor, data, reply);
            sp<IVehicleMonitorListener> listener =
                    interface_cast<IVehicleMonitorListener>(data.readStrongBinder());
            r = setMonitorListener(listener);
            reply->writeNoException();
            return r;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

}; // namespace android