1061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown/*
2061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * Copyright (C) 2010 The Android Open Source Project
3061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown *
4061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * you may not use this file except in compliance with the License.
6061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * You may obtain a copy of the License at
7061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown *
8061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown *
10061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * Unless required by applicable law or agreed to in writing, software
11061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * See the License for the specific language governing permissions and
14061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown * limitations under the License.
15061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown */
16061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
175bf842b22e79d779d82d5a1cc84b57b7ff7bd846Jeff Brown#include <androidfw/KeyCharacterMap.h>
185bf842b22e79d779d82d5a1cc84b57b7ff7bd846Jeff Brown#include <androidfw/KeyLayoutMap.h>
195bf842b22e79d779d82d5a1cc84b57b7ff7bd846Jeff Brown#include <androidfw/VirtualKeyMap.h>
206f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown#include <utils/PropertyMap.h>
21061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown#include <utils/String8.h>
22061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
23061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown#include <stdio.h>
24061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown#include <stdlib.h>
25061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown#include <string.h>
26061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
27061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownusing namespace android;
28061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
29061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownstatic const char* gProgName = "validatekeymaps";
30061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
31061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownenum FileType {
32061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    FILETYPE_UNKNOWN,
33061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    FILETYPE_KEYLAYOUT,
34061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    FILETYPE_KEYCHARACTERMAP,
359065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    FILETYPE_VIRTUALKEYDEFINITION,
366f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    FILETYPE_INPUTDEVICECONFIGURATION,
37061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown};
38061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
39061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
40061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownstatic void usage() {
41061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    fprintf(stderr, "Keymap Validation Tool\n\n");
42061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    fprintf(stderr, "Usage:\n");
43061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    fprintf(stderr,
446f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        " %s [*.kl] [*.kcm] [*.idc] [virtualkeys.*] [...]\n"
456f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        "   Validates the specified key layouts, key character maps, \n"
466f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        "   input device configurations, or virtual key definitions.\n\n",
479065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        gProgName);
48061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown}
49061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
50061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownstatic FileType getFileType(const char* filename) {
51ab841350f99fad48c1bdeb0f62c1713fcfcbf437Jeff Brown    const char *extension = strrchr(filename, '.');
52061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    if (extension) {
53061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        if (strcmp(extension, ".kl") == 0) {
54061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            return FILETYPE_KEYLAYOUT;
55061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        }
56061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        if (strcmp(extension, ".kcm") == 0) {
57061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            return FILETYPE_KEYCHARACTERMAP;
58061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        }
596f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        if (strcmp(extension, ".idc") == 0) {
606f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            return FILETYPE_INPUTDEVICECONFIGURATION;
616f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        }
62061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
639065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
649065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    if (strstr(filename, "virtualkeys.")) {
659065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        return FILETYPE_VIRTUALKEYDEFINITION;
669065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    }
679065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
68061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    return FILETYPE_UNKNOWN;
69061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown}
70061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
71061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownstatic bool validateFile(const char* filename) {
72061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    fprintf(stdout, "Validating file '%s'...\n", filename);
73061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
74061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    FileType fileType = getFileType(filename);
75061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    switch (fileType) {
76061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    case FILETYPE_UNKNOWN:
779065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        fprintf(stderr, "Supported file types: *.kl, *.kcm, virtualkeys.*\n\n");
78061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        return false;
79061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
80061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    case FILETYPE_KEYLAYOUT: {
819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        sp<KeyLayoutMap> map;
82061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        status_t status = KeyLayoutMap::load(String8(filename), &map);
83061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        if (status) {
84061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            fprintf(stderr, "Error %d parsing key layout file.\n\n", status);
85061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            return false;
86061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        }
87061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        break;
88061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
89061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
90061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    case FILETYPE_KEYCHARACTERMAP: {
919f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        sp<KeyCharacterMap> map;
926ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        status_t status = KeyCharacterMap::load(String8(filename),
936ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                KeyCharacterMap::FORMAT_ANY, &map);
94061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        if (status) {
95061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            fprintf(stderr, "Error %d parsing key character map file.\n\n", status);
96061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            return false;
97061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        }
98061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        break;
99061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
1009065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
1016f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    case FILETYPE_INPUTDEVICECONFIGURATION: {
1026f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        PropertyMap* map;
1036f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        status_t status = PropertyMap::load(String8(filename), &map);
1046f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        if (status) {
1056f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            fprintf(stderr, "Error %d parsing input device configuration file.\n\n", status);
1066f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            return false;
1076f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        }
1089f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        delete map;
1096f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        break;
1106f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
1116f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
1129065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    case FILETYPE_VIRTUALKEYDEFINITION: {
1139065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        VirtualKeyMap* map;
1149065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        status_t status = VirtualKeyMap::load(String8(filename), &map);
1159065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (status) {
1169065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            fprintf(stderr, "Error %d parsing virtual key definition file.\n\n", status);
1179065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            return false;
1189065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        }
1199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        delete map;
1209065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        break;
1219065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    }
122061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
123061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
124061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    fputs("No errors.\n\n", stdout);
125061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    return true;
126061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown}
127061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
128061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brownint main(int argc, const char** argv) {
129061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    if (argc < 2) {
130061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        usage();
131061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        return 1;
132061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
133061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
134061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    int result = 0;
135061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    for (int i = 1; i < argc; i++) {
136061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        if (!validateFile(argv[i])) {
137061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown            result = 1;
138061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        }
139061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
140061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown
141061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    if (result) {
142061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        fputs("Failed!\n", stderr);
143061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    } else {
144061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown        fputs("Success.\n", stdout);
145061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    }
146061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown    return result;
147061cf758841dfc972be3f0ec4857762fafe49aa6Jeff Brown}
148