1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <binder/Binder.h>
18 #include <binder/Parcel.h>
19 #include <gtest/gtest.h>
20 #include <input/InputDevice.h>
21 #include <input/KeyLayoutMap.h>
22 #include <input/Keyboard.h>
23 #include "android-base/file.h"
24
25 namespace android {
26
27 // --- InputDeviceIdentifierTest ---
28
TEST(InputDeviceIdentifierTest,getCanonicalName)29 TEST(InputDeviceIdentifierTest, getCanonicalName) {
30 InputDeviceIdentifier identifier;
31 identifier.name = "test device";
32 ASSERT_EQ(std::string("test_device"), identifier.getCanonicalName());
33
34 identifier.name = "deviceName-123 version_C!";
35 ASSERT_EQ(std::string("deviceName-123_version_C_"), identifier.getCanonicalName());
36 }
37
38 class InputDeviceKeyMapTest : public testing::Test {
39 protected:
loadKeyLayout(const char * name)40 void loadKeyLayout(const char* name) {
41 std::string path =
42 getInputDeviceConfigurationFilePathByName(name,
43 InputDeviceConfigurationFileType::
44 KEY_LAYOUT);
45 ASSERT_FALSE(path.empty());
46 base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(path);
47 ASSERT_TRUE(ret.ok()) << "Cannot load KeyLayout at " << path;
48 mKeyMap.keyLayoutMap = std::move(*ret);
49 mKeyMap.keyLayoutFile = path;
50 }
51
loadKeyCharacterMap(const char * name)52 void loadKeyCharacterMap(const char* name) {
53 InputDeviceIdentifier identifier;
54 identifier.name = name;
55 std::string path =
56 getInputDeviceConfigurationFilePathByName(identifier.getCanonicalName(),
57 InputDeviceConfigurationFileType::
58 KEY_CHARACTER_MAP);
59 ASSERT_FALSE(path.empty()) << "KeyCharacterMap for " << name << " not found";
60 base::Result<std::shared_ptr<KeyCharacterMap>> ret =
61 KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE);
62 ASSERT_TRUE(ret.ok()) << "Cannot load KeyCharacterMap at " << path;
63 mKeyMap.keyCharacterMap = *ret;
64 mKeyMap.keyCharacterMapFile = path;
65 }
66
SetUp()67 virtual void SetUp() override {
68 loadKeyLayout("Generic");
69 loadKeyCharacterMap("Generic");
70 }
71
TearDown()72 virtual void TearDown() override {}
73
74 KeyMap mKeyMap;
75 };
76
TEST_F(InputDeviceKeyMapTest,keyCharacterMapParcelingTest)77 TEST_F(InputDeviceKeyMapTest, keyCharacterMapParcelingTest) {
78 Parcel parcel;
79 mKeyMap.keyCharacterMap->writeToParcel(&parcel);
80 parcel.setDataPosition(0);
81 std::shared_ptr<KeyCharacterMap> map = KeyCharacterMap::readFromParcel(&parcel);
82 // Verify the key character map is the same as original
83 ASSERT_EQ(*map, *mKeyMap.keyCharacterMap);
84 }
85
TEST_F(InputDeviceKeyMapTest,keyCharacterMapWithOverlayParcelingTest)86 TEST_F(InputDeviceKeyMapTest, keyCharacterMapWithOverlayParcelingTest) {
87 Parcel parcel;
88 std::string overlayPath = base::GetExecutableDirectory() + "/data/german.kcm";
89 base::Result<std::shared_ptr<KeyCharacterMap>> overlay =
90 KeyCharacterMap::load(overlayPath, KeyCharacterMap::Format::OVERLAY);
91 ASSERT_TRUE(overlay.ok()) << "Cannot load KeyCharacterMap at " << overlayPath;
92 mKeyMap.keyCharacterMap->combine(*overlay->get());
93 mKeyMap.keyCharacterMap->writeToParcel(&parcel);
94 parcel.setDataPosition(0);
95 std::shared_ptr<KeyCharacterMap> map = KeyCharacterMap::readFromParcel(&parcel);
96 ASSERT_EQ(*map, *mKeyMap.keyCharacterMap);
97 }
98
TEST_F(InputDeviceKeyMapTest,keyCharacteMapApplyMultipleOverlaysTest)99 TEST_F(InputDeviceKeyMapTest, keyCharacteMapApplyMultipleOverlaysTest) {
100 std::string frenchOverlayPath = base::GetExecutableDirectory() + "/data/french.kcm";
101 std::string englishOverlayPath = base::GetExecutableDirectory() + "/data/english_us.kcm";
102 std::string germanOverlayPath = base::GetExecutableDirectory() + "/data/german.kcm";
103 base::Result<std::shared_ptr<KeyCharacterMap>> frenchOverlay =
104 KeyCharacterMap::load(frenchOverlayPath, KeyCharacterMap::Format::OVERLAY);
105 ASSERT_TRUE(frenchOverlay.ok()) << "Cannot load KeyCharacterMap at " << frenchOverlayPath;
106 base::Result<std::shared_ptr<KeyCharacterMap>> englishOverlay =
107 KeyCharacterMap::load(englishOverlayPath, KeyCharacterMap::Format::OVERLAY);
108 ASSERT_TRUE(englishOverlay.ok()) << "Cannot load KeyCharacterMap at " << englishOverlayPath;
109 base::Result<std::shared_ptr<KeyCharacterMap>> germanOverlay =
110 KeyCharacterMap::load(germanOverlayPath, KeyCharacterMap::Format::OVERLAY);
111 ASSERT_TRUE(germanOverlay.ok()) << "Cannot load KeyCharacterMap at " << germanOverlayPath;
112
113 // Apply the French overlay
114 mKeyMap.keyCharacterMap->combine(*frenchOverlay->get());
115 // Copy the result for later
116 std::shared_ptr<KeyCharacterMap> frenchOverlaidKeyCharacterMap =
117 std::make_shared<KeyCharacterMap>(*mKeyMap.keyCharacterMap);
118
119 // Apply the English overlay
120 mKeyMap.keyCharacterMap->combine(*englishOverlay->get());
121 // Verify that the result is different from the French overlay result
122 ASSERT_NE(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
123
124 // Apply the German overlay
125 mKeyMap.keyCharacterMap->combine(*germanOverlay->get());
126 // Verify that the result is different from the French overlay result
127 ASSERT_NE(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
128
129 // Apply the French overlay
130 mKeyMap.keyCharacterMap->combine(*frenchOverlay->get());
131 // Verify that the result is the same like after applying it initially
132 ASSERT_EQ(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
133 }
134
135 } // namespace android
136