1 /*
2  * Copyright (C) 2016 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 #define LOG_TAG "memtrack_hidl_hal_test"
18 #include <android-base/logging.h>
19 #include <android-base/unique_fd.h>
20 
21 #include <android/hardware/memtrack/1.0/IMemtrack.h>
22 
23 #include <gtest/gtest.h>
24 #include <hidl/GtestPrinter.h>
25 #include <hidl/ServiceManagement.h>
26 
27 #include <fcntl.h>
28 #include <algorithm>
29 #include <vector>
30 
31 using ::android::hardware::memtrack::V1_0::IMemtrack;
32 using ::android::hardware::memtrack::V1_0::MemtrackRecord;
33 using ::android::hardware::memtrack::V1_0::MemtrackFlag;
34 using ::android::hardware::memtrack::V1_0::MemtrackType;
35 using ::android::hardware::memtrack::V1_0::MemtrackStatus;
36 using ::android::hardware::hidl_vec;
37 using ::android::hardware::Return;
38 using ::android::sp;
39 using ::android::base::unique_fd;
40 using std::vector;
41 using std::count_if;
42 
43 class MemtrackHidlTest : public ::testing::TestWithParam<std::string> {
44  public:
SetUp()45   virtual void SetUp() override {
46       memtrack = IMemtrack::getService(GetParam());
47       ASSERT_NE(memtrack, nullptr);
48   }
49 
TearDown()50   virtual void TearDown() override {}
51 
52   sp<IMemtrack> memtrack;
53 };
54 
55 /* Returns true if flags contains at least min, and no more than max,
56  * of the flags in flagSet. Returns false otherwise.
57  */
rightFlagCount(uint32_t flags,vector<MemtrackFlag> flagSet,uint32_t min,uint32_t max)58 bool rightFlagCount(uint32_t flags, vector<MemtrackFlag> flagSet, uint32_t min,
59                     uint32_t max) {
60   uint32_t count =
61       count_if(flagSet.begin(), flagSet.end(),
62                [&](MemtrackFlag f) { return flags & (uint32_t)f; });
63   return (min <= count && count <= max);
64 }
65 
66 /* Returns true when passed a valid, defined status, false otherwise.
67  */
validStatus(MemtrackStatus s)68 bool validStatus(MemtrackStatus s) {
69   vector<MemtrackStatus> statusVec = {
70       MemtrackStatus::SUCCESS, MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED,
71       MemtrackStatus::TYPE_NOT_SUPPORTED};
72   return std::find(statusVec.begin(), statusVec.end(), s) != statusVec.end();
73 }
74 
generate_cb(MemtrackStatus * s,hidl_vec<MemtrackRecord> * v)75 auto generate_cb(MemtrackStatus *s, hidl_vec<MemtrackRecord> *v) {
76   return [=](MemtrackStatus status, hidl_vec<MemtrackRecord> vec) {
77     *s = status;
78     *v = vec;
79   };
80 }
81 
82 /* Sanity check results when getMemory() is passed a negative PID
83  */
TEST_P(MemtrackHidlTest,BadPidTest)84 TEST_P(MemtrackHidlTest, BadPidTest) {
85   MemtrackStatus s;
86   hidl_vec<MemtrackRecord> v;
87   auto cb = generate_cb(&s, &v);
88   for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
89        i++) {
90     Return<void> ret =
91         memtrack->getMemory(-1, static_cast<MemtrackType>(i), cb);
92     ASSERT_TRUE(ret.isOk());
93     ASSERT_TRUE(validStatus(s));
94   }
95 }
96 
97 /* Sanity check results when getMemory() is passed a bad memory usage type
98  */
TEST_P(MemtrackHidlTest,BadTypeTest)99 TEST_P(MemtrackHidlTest, BadTypeTest) {
100   MemtrackStatus s;
101   hidl_vec<MemtrackRecord> v;
102   auto cb = generate_cb(&s, &v);
103   Return<void> ret = memtrack->getMemory(getpid(), MemtrackType::NUM_TYPES, cb);
104   ASSERT_TRUE(ret.isOk());
105   ASSERT_TRUE(validStatus(s));
106 }
107 
108 /* Call memtrack on this process and check that the results are reasonable
109  * for all memory types, including valid flag combinations for every
110  * MemtrackRecord returned.
111  */
TEST_P(MemtrackHidlTest,GetMemoryTest)112 TEST_P(MemtrackHidlTest, GetMemoryTest) {
113   /* Opening this device causes the kernel to provide memtrack with memory
114    * info for this process.
115    */
116   unique_fd fd(open("/dev/kgsl-3d0", O_RDWR));
117 
118   MemtrackStatus s;
119   hidl_vec<MemtrackRecord> v;
120   auto cb = generate_cb(&s, &v);
121   uint32_t unsupportedCount = 0;
122   for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
123        i++) {
124     Return<void> ret =
125         memtrack->getMemory(getpid(), static_cast<MemtrackType>(i), cb);
126     ASSERT_TRUE(ret.isOk());
127 
128     switch (s) {
129       case MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
130         unsupportedCount++;
131         break;
132       case MemtrackStatus::TYPE_NOT_SUPPORTED:
133         break;
134       case MemtrackStatus::SUCCESS: {
135         for (uint32_t j = 0; j < v.size(); j++) {
136           // Enforce flag constraints
137           vector<MemtrackFlag> smapFlags = {MemtrackFlag::SMAPS_ACCOUNTED,
138                                             MemtrackFlag::SMAPS_UNACCOUNTED};
139           EXPECT_TRUE(rightFlagCount(v[j].flags, smapFlags, 1, 1));
140           vector<MemtrackFlag> shareFlags = {MemtrackFlag::SHARED,
141                                              MemtrackFlag::SHARED_PSS,
142                                              MemtrackFlag::PRIVATE};
143           EXPECT_TRUE(rightFlagCount(v[j].flags, shareFlags, 0, 1));
144           vector<MemtrackFlag> systemFlags = {MemtrackFlag::SYSTEM,
145                                               MemtrackFlag::DEDICATED};
146           EXPECT_TRUE(rightFlagCount(v[j].flags, systemFlags, 0, 1));
147           vector<MemtrackFlag> secureFlags = {MemtrackFlag::SECURE,
148                                               MemtrackFlag::NONSECURE};
149           EXPECT_TRUE(rightFlagCount(v[j].flags, secureFlags, 0, 1));
150         }
151         break;
152       }
153       default:
154         FAIL();
155     }
156   }
157   // If tracking is not supported this should be returned for all types.
158   ASSERT_TRUE(unsupportedCount == 0 ||
159               unsupportedCount ==
160                   static_cast<uint32_t>(MemtrackType::NUM_TYPES));
161 }
162 
163 INSTANTIATE_TEST_SUITE_P(
164         PerInstance, MemtrackHidlTest,
165         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMemtrack::descriptor)),
166         android::hardware::PrintInstanceNameToString);
167