1 /*
2  * Copyright (C) 2024 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 <media/NativePermissionController.h>
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <error/BinderStatusMatcher.h>
23 #include <error/ExpectedMatchers.h>
24 
25 using android::binder::Status::EX_ILLEGAL_ARGUMENT;
26 using android::binder::Status::EX_ILLEGAL_STATE;
27 using android::error::BinderStatusMatcher;
28 using android::error::IsErrorAnd;
29 using android::error::IsOkAnd;
30 using com::android::media::permission::NativePermissionController;
31 using com::android::media::permission::PermissionEnum;
32 using com::android::media::permission::UidPackageState;
33 
34 using ::testing::ElementsAre;
35 using ::testing::IsFalse;
36 using ::testing::IsTrue;
37 
38 class NativePermissionControllerTest : public ::testing::Test {
39   protected:
40     android::sp<NativePermissionController> holder_ =
41             android::sp<NativePermissionController>::make();
42     NativePermissionController& controller_ = *holder_;
43 };
createState(uid_t uid,std::vector<std::string> packagesNames)44 static UidPackageState createState(uid_t uid, std::vector<std::string> packagesNames) {
45     UidPackageState out{};
46     out.uid = uid;
47     out.packageNames = std::move(packagesNames);
48     return out;
49 }
50 
51 // ---  Tests for non-populated ----
TEST_F(NativePermissionControllerTest,getPackagesForUid_NotPopulated)52 TEST_F(NativePermissionControllerTest, getPackagesForUid_NotPopulated) {
53     // Verify errors are returned
54     EXPECT_THAT(controller_.getPackagesForUid(10000),
55                 IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
56     EXPECT_THAT(controller_.getPackagesForUid(10001),
57                 IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
58 
59     // fixed uids should work
60     EXPECT_THAT(controller_.getPackagesForUid(1000), IsOkAnd(ElementsAre(std::string{"system"})));
61 }
62 
TEST_F(NativePermissionControllerTest,validateUidPackagePair_NotPopulated)63 TEST_F(NativePermissionControllerTest, validateUidPackagePair_NotPopulated) {
64     // Verify errors are returned
65     EXPECT_THAT(controller_.validateUidPackagePair(10000, "com.package"),
66                 IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
67 
68     // fixed uids should work
69     EXPECT_THAT(controller_.validateUidPackagePair(1000, "system"), IsOkAnd(IsTrue()));
70 }
71 
72 // ---  Tests for populatePackagesForUids ----
TEST_F(NativePermissionControllerTest,populatePackages_EmptyInput)73 TEST_F(NativePermissionControllerTest, populatePackages_EmptyInput) {
74     std::vector<UidPackageState> input;
75 
76     // succeeds
77     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
78 
79     // Verify unknown uid behavior
80     EXPECT_THAT(controller_.getPackagesForUid(10000),
81                 IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
82 }
83 
TEST_F(NativePermissionControllerTest,populatePackages_ValidInput)84 TEST_F(NativePermissionControllerTest, populatePackages_ValidInput) {
85     std::vector<UidPackageState> input{
86             createState(10000, {"com.example.app1", "com.example.app2"}),
87             createState(10001, {"com.example2.app1"}),
88     };
89 
90     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
91 
92     EXPECT_THAT(controller_.getPackagesForUid(10000),
93                 IsOkAnd(ElementsAre("com.example.app1", "com.example.app2")));
94     EXPECT_THAT(controller_.getPackagesForUid(10001), IsOkAnd(ElementsAre("com.example2.app1")));
95 }
96 
97 // --- Tests for updatePackagesForUid ---
TEST_F(NativePermissionControllerTest,updatePackages_NewUid)98 TEST_F(NativePermissionControllerTest, updatePackages_NewUid) {
99     std::vector<UidPackageState> input{
100             createState(10000, {"com.example.app1", "com.example.app2"}),
101             createState(10001, {"com.example2.app1"}),
102     };
103     UidPackageState newState = createState(12000, {"com.example.other"});
104 
105     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
106     EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
107 
108     // Verify the results: only the updated package should be changed
109     EXPECT_THAT(controller_.getPackagesForUid(10000),
110                 IsOkAnd(ElementsAre("com.example.app1", "com.example.app2")));
111     EXPECT_THAT(controller_.getPackagesForUid(10001), IsOkAnd(ElementsAre("com.example2.app1")));
112     EXPECT_THAT(controller_.getPackagesForUid(12000), IsOkAnd(ElementsAre("com.example.other")));
113 }
114 
TEST_F(NativePermissionControllerTest,updatePackages_ExistingUid)115 TEST_F(NativePermissionControllerTest, updatePackages_ExistingUid) {
116     std::vector<UidPackageState> input{
117             createState(10000, {"com.example.app1", "com.example.app2", "com.example.app3"}),
118             createState(10001, {"com.example2.app1"}),
119     };
120 
121     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
122     // Update packages for existing uid
123     UidPackageState newState = createState(10000, {"com.example.other", "com.example.new"});
124     EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
125 
126     // Verify update
127     EXPECT_THAT(controller_.getPackagesForUid(10000),
128                 IsOkAnd(ElementsAre("com.example.other", "com.example.new")));
129 }
130 
TEST_F(NativePermissionControllerTest,updatePackages_EmptyRemovesEntry)131 TEST_F(NativePermissionControllerTest, updatePackages_EmptyRemovesEntry) {
132     std::vector<UidPackageState> input{
133             createState(10000, {"com.example.app1"}),
134     };
135 
136     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
137 
138     UidPackageState newState{};  // Empty package list
139     newState.uid = 10000;
140     EXPECT_THAT(controller_.updatePackagesForUid(newState), BinderStatusMatcher::isOk());
141     // getPackages for unknown UID should error out
142     EXPECT_THAT(controller_.getPackagesForUid(10000),
143                 IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT)));
144 }
145 
TEST_F(NativePermissionControllerTest,validateUidPackagePair_ValidPair)146 TEST_F(NativePermissionControllerTest, validateUidPackagePair_ValidPair) {
147     std::vector<UidPackageState> input{
148             createState(10000, {"com.example.app1", "com.example.app2"}),
149     };
150 
151     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
152 
153     EXPECT_THAT(controller_.validateUidPackagePair(10000, "com.example.app1"), IsOkAnd(IsTrue()));
154 }
155 
TEST_F(NativePermissionControllerTest,validateUidPackagePair_InvalidPackage)156 TEST_F(NativePermissionControllerTest, validateUidPackagePair_InvalidPackage) {
157     std::vector<UidPackageState> input{
158             createState(10000, {"com.example.app1", "com.example.app2"}),
159     };
160 
161     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
162 
163     EXPECT_THAT(controller_.validateUidPackagePair(10000, "com.example.other"), IsOkAnd(IsFalse()));
164 }
165 
TEST_F(NativePermissionControllerTest,validateUidPackagePair_UnknownUid)166 TEST_F(NativePermissionControllerTest, validateUidPackagePair_UnknownUid) {
167     std::vector<UidPackageState> input{
168             createState(10000, {"com.example.app1", "com.example.app2"}),
169     };
170 
171     EXPECT_THAT(controller_.populatePackagesForUids(input), BinderStatusMatcher::isOk());
172 
173     EXPECT_THAT(controller_.validateUidPackagePair(12000, "any.package"), IsOkAnd(IsFalse()));
174 }
175 
TEST_F(NativePermissionControllerTest,populatePermissionState_InvalidPermission)176 TEST_F(NativePermissionControllerTest, populatePermissionState_InvalidPermission) {
177     EXPECT_THAT(controller_.populatePermissionState(PermissionEnum::ENUM_SIZE, {}),
178                 BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT));
179     EXPECT_THAT(
180             controller_.populatePermissionState(
181                     static_cast<PermissionEnum>(static_cast<int>(PermissionEnum::ENUM_SIZE) + 1),
182                     {}),
183             BinderStatusMatcher::hasException(EX_ILLEGAL_ARGUMENT));
184 }
185 
TEST_F(NativePermissionControllerTest,populatePermissionState_HoldsPermission)186 TEST_F(NativePermissionControllerTest, populatePermissionState_HoldsPermission) {
187     // Unsorted
188     std::vector<int> uids{3, 1, 2, 4, 5};
189 
190     EXPECT_THAT(controller_.populatePermissionState(PermissionEnum::MODIFY_AUDIO_ROUTING, uids),
191                 BinderStatusMatcher::isOk());
192 
193     EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3),
194                 IsOkAnd(IsTrue()));
195 }
196 
TEST_F(NativePermissionControllerTest,populatePermissionState_DoesNotHoldPermission)197 TEST_F(NativePermissionControllerTest, populatePermissionState_DoesNotHoldPermission) {
198     // Unsorted
199     std::vector<int> uids{3, 1, 2, 4, 5};
200 
201     EXPECT_THAT(controller_.populatePermissionState(PermissionEnum::MODIFY_AUDIO_ROUTING, uids),
202                 BinderStatusMatcher::isOk());
203 
204     EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 6),
205                 IsOkAnd(IsFalse()));
206 }
207 
TEST_F(NativePermissionControllerTest,populatePermissionState_NotInitialized)208 TEST_F(NativePermissionControllerTest, populatePermissionState_NotInitialized) {
209     EXPECT_THAT(controller_.checkPermission(PermissionEnum::MODIFY_AUDIO_ROUTING, 3),
210                 IsErrorAnd(BinderStatusMatcher::hasException(EX_ILLEGAL_STATE)));
211 }
212