1fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall/*
2fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * Copyright 2016 The Android Open Source Project
3fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall *
4fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
5fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * you may not use this file except in compliance with the License.
6fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * You may obtain a copy of the License at
7fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall *
8fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
9fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall *
10fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * Unless required by applicable law or agreed to in writing, software
11fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
12fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * See the License for the specific language governing permissions and
14fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall * limitations under the License.
15fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall */
16fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
17fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall#include "GpuService.h"
18fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
19fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall#include <binder/Parcel.h>
208b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall#include <utils/String8.h>
218b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall#include <vkjson.h>
22fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
23fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hallnamespace android {
24fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
25fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall// ----------------------------------------------------------------------------
26fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
27fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hallclass BpGpuService : public BpInterface<IGpuService>
28fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall{
29fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hallpublic:
30fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
31fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall};
32fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
33fc038bd8fc77998a436d43027919f4500c4291e6Jesse HallIMPLEMENT_META_INTERFACE(GpuService, "android.ui.IGpuService");
34fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
35fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hallstatus_t BnGpuService::onTransact(uint32_t code, const Parcel& data,
36fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        Parcel* reply, uint32_t flags)
37fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall{
38fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    switch (code) {
39fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    case SHELL_COMMAND_TRANSACTION: {
40fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        int in = data.readFileDescriptor();
41fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        int out = data.readFileDescriptor();
42fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        int err = data.readFileDescriptor();
43fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        int argc = data.readInt32();
44fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        Vector<String16> args;
45fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
46fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall           args.add(data.readString16());
47fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        }
48fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        return shellCommand(in, out, err, args);
49fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    }
50fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
51fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    default:
52fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall        return BBinder::onTransact(code, data, reply, flags);
53fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    }
54fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall}
55fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
56fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall// ----------------------------------------------------------------------------
57fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
588b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hallnamespace {
598b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    status_t cmd_help(int out);
608b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    status_t cmd_vkjson(int out, int err);
618b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall}
628b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
63fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hallconst char* const GpuService::SERVICE_NAME = "gpu";
64fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
65fc038bd8fc77998a436d43027919f4500c4291e6Jesse HallGpuService::GpuService() {}
66fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
678b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hallstatus_t GpuService::shellCommand(int /*in*/, int out, int err,
688b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        Vector<String16>& args)
69fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall{
708b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    ALOGV("GpuService::shellCommand");
718b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    for (size_t i = 0, n = args.size(); i < n; i++)
728b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        ALOGV("  arg[%zu]: '%s'", i, String8(args[i]).string());
738b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
748b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (args[0] == String16("vkjson"))
758b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return cmd_vkjson(out, err);
768b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    else if (args[0] == String16("help"))
778b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return cmd_help(out);
788b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
798b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    return NO_ERROR;
808b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall}
818b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
828b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall// ----------------------------------------------------------------------------
838b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
848b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hallnamespace {
858b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
868b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hallstatus_t cmd_help(int out) {
878b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    FILE* outs = fdopen(out, "w");
888b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (!outs) {
898b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno),
908b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall            errno);
918b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return BAD_VALUE;
928b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
938b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    fprintf(outs,
948b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        "GPU Service commands:\n"
958b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        "  vkjson   dump Vulkan device capabilities as JSON\n");
968b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    fclose(outs);
97fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall    return NO_ERROR;
98fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall}
99fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall
1008b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse HallVkResult vkjsonPrint(FILE* out, FILE* err) {
1018b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    VkResult result;
1028b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1038b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    const VkApplicationInfo app_info = {
1048b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr,
1058b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        "vkjson", 1,    /* app name, version */
1068b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        "", 0,          /* engine name, version */
1072676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        VK_API_VERSION_1_0
1088b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    };
1098b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    const VkInstanceCreateInfo instance_info = {
1108b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr,
1118b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        0,              /* flags */
1128b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        &app_info,
1138b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        0, nullptr,     /* layers */
1148b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        0, nullptr,     /* extensions */
1158b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    };
1168b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    VkInstance instance;
1178b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    result = vkCreateInstance(&instance_info, nullptr, &instance);
1188b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (result != VK_SUCCESS) {
1198b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        fprintf(err, "vkCreateInstance failed: %d\n", result);
1208b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return result;
1218b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
1228b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1238b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    uint32_t ngpu = 0;
1248b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr);
1258b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (result != VK_SUCCESS) {
1268b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
1278b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return result;
1288b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
1298b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE);
1308b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data());
1318b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (result != VK_SUCCESS) {
1328b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
1338b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return result;
1348b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
1358b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1368b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    for (size_t i = 0, n = gpus.size(); i < n; i++) {
1378b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        auto props = VkJsonGetAllProperties(gpus[i]);
1388b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        std::string json = VkJsonAllPropertiesToJson(props);
1398b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        fwrite(json.data(), 1, json.size(), out);
1408b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        if (i < n - 1)
1418b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall            fputc(',', out);
1428b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        fputc('\n', out);
1438b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
1448b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1458b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    vkDestroyInstance(instance, nullptr);
1468b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1478b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    return VK_SUCCESS;
1488b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall}
1498b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1508b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hallstatus_t cmd_vkjson(int out, int err) {
1518b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    int errnum;
1528b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    FILE* outs = fdopen(out, "w");
1538b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (!outs) {
1548b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        errnum = errno;
1558b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        ALOGE("vkjson: failed to create output stream: %s", strerror(errnum));
1568b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return -errnum;
1578b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
1588b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    FILE* errs = fdopen(err, "w");
1598b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    if (!errs) {
1608b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        errnum = errno;
1618b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        ALOGE("vkjson: failed to create error stream: %s", strerror(errnum));
1628b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        fclose(outs);
1638b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall        return -errnum;
1648b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    }
1658b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    fprintf(outs, "[\n");
1668b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    VkResult result = vkjsonPrint(outs, errs);
1678b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    fprintf(outs, "]\n");
1688b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    fclose(errs);
1698b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    fclose(outs);
1708b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall    return result >= 0 ? NO_ERROR : UNKNOWN_ERROR;
1718b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall}
1728b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
1738b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall} // anonymous namespace
1748b0d55e3652e68e9e2b0f4314c1eaeadc49cc2d0Jesse Hall
175fc038bd8fc77998a436d43027919f4500c4291e6Jesse Hall} // namespace android
176