• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android/content/AttributionSourceState.h>
18 #include <media/AppOpsSession.h>
19 #include <media/ValidatedAttributionSourceState.h>
20 
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 
24 #include <functional>
25 
26 using ::android::content::AttributionSourceState;
27 using ::android::media::permission::AppOpsSession;
28 using ::android::media::permission::Ops;
29 using ::com::android::media::permission::ValidatedAttributionSourceState;
30 
31 using ::testing::ElementsAreArray;
32 using ::testing::IsEmpty;
33 using ::testing::Ne;
34 
35 class AppOpsSessionTests;
36 
37 class AppOpsTestFacade {
38     friend AppOpsSessionTests;
39 
40   public:
startAccess(const ValidatedAttributionSourceState &,Ops)41     bool startAccess(const ValidatedAttributionSourceState&, Ops) {
42         if (allowed_) ++running_;
43         return allowed_;
44     }
45 
stopAccess(const ValidatedAttributionSourceState &,Ops)46     void stopAccess(const ValidatedAttributionSourceState&, Ops) { --running_; }
47 
checkAccess(const ValidatedAttributionSourceState &,Ops)48     bool checkAccess(const ValidatedAttributionSourceState&, Ops) { return allowed_; }
49 
addChangeCallback(const ValidatedAttributionSourceState &,Ops,std::function<void (bool)> cb)50     uintptr_t addChangeCallback(const ValidatedAttributionSourceState&, Ops,
51                                 std::function<void(bool)> cb) {
52         cb_ = cb;
53         return 42;
54     }
55 
removeChangeCallback(uintptr_t)56     void removeChangeCallback(uintptr_t) {}
57 
58   private:
59     // Static abuse since this is copied into the test, and represents "global" state
60     static inline std::function<void(bool)> cb_;
61     static inline bool allowed_;
62     static inline int running_;
63 };
64 
65 class AppOpsSessionTests : public ::testing::Test {
66   protected:
67     static constexpr Ops mOps = {100, 101};
68 
69     // We must manually clear the facade state, since it is static, unlike the members of this
70     // class, since the fixture is constructed per-test.
SetUp()71     void SetUp() override {
72         AppOpsTestFacade::cb_ = nullptr;
73         AppOpsTestFacade::running_ = 0;
74         AppOpsTestFacade::allowed_ = false;
75     }
76 
facadeSetAllowed(bool isAllowed)77     void facadeSetAllowed(bool isAllowed) { AppOpsTestFacade::allowed_ = isAllowed; }
78 
facadeGetRunning()79     int facadeGetRunning() { return AppOpsTestFacade::running_; }
80 
facadeTriggerChange(bool isPermitted)81     void facadeTriggerChange(bool isPermitted) {
82         EXPECT_THAT(isPermitted, Ne(AppOpsTestFacade::allowed_));
83         facadeSetAllowed(isPermitted);
84         AppOpsTestFacade::cb_(isPermitted);
85     }
86 
87     // Trigger a change callback, but without modifying the underlying state.
88     // Allows for simulating a callback which is reversed quickly and callbacks which may not
89     // apply to our package.
facadeTriggerSpuriousChange(bool isPermitted)90     void facadeTriggerSpuriousChange(bool isPermitted) { facadeSetAllowed(isPermitted); }
91 
dataDeliveryCb(bool shouldDeliver)92     void dataDeliveryCb(bool shouldDeliver) { mDeliveredCbs.push_back(shouldDeliver); }
93 
__anonda944ad80102() 94     const AttributionSourceState mAttr = []() {
95         AttributionSourceState attr;
96         attr.uid = 1;
97         attr.pid = 2;
98         attr.deviceId = 3;
99         return attr;
100     }();
101 
initSession()102     void initSession() {
103         mAppOpsSession.emplace(
104                 ValidatedAttributionSourceState::createFromTrustedSource(mAttr), mOps,
105                 [this](bool x) { dataDeliveryCb(x); }, AppOpsTestFacade{});
106     }
107 
108     // For verification of delivered callbacks
109     // vector<bool> since it's a test
110     std::vector<bool> mDeliveredCbs;
111     std::optional<AppOpsSession<AppOpsTestFacade>> mAppOpsSession;
112 };
113 
TEST_F(AppOpsSessionTests,beginDeliveryRequest_Allowed)114 TEST_F(AppOpsSessionTests, beginDeliveryRequest_Allowed) {
115     facadeSetAllowed(true);
116     initSession();
117     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
118     EXPECT_EQ(facadeGetRunning(), 1);
119 
120     EXPECT_THAT(mDeliveredCbs, IsEmpty());
121 }
122 
TEST_F(AppOpsSessionTests,beginDeliveryRequest_Denied)123 TEST_F(AppOpsSessionTests, beginDeliveryRequest_Denied) {
124     facadeSetAllowed(false);
125     initSession();
126     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
127     EXPECT_EQ(facadeGetRunning(), 0);
128 
129     EXPECT_THAT(mDeliveredCbs, IsEmpty());
130 }
131 
TEST_F(AppOpsSessionTests,endDeliveryRequest_Ongoing)132 TEST_F(AppOpsSessionTests, endDeliveryRequest_Ongoing) {
133     facadeSetAllowed(true);
134     initSession();
135     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
136     EXPECT_EQ(facadeGetRunning(), 1);
137     mAppOpsSession->endDeliveryRequest();
138     EXPECT_EQ(facadeGetRunning(), 0);
139 
140     EXPECT_THAT(mDeliveredCbs, IsEmpty());
141 }
142 
TEST_F(AppOpsSessionTests,endDeliveryRequest_Paused)143 TEST_F(AppOpsSessionTests, endDeliveryRequest_Paused) {
144     facadeSetAllowed(false);
145     initSession();
146     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
147     EXPECT_EQ(facadeGetRunning(), 0);
148     mAppOpsSession->endDeliveryRequest();
149     EXPECT_EQ(facadeGetRunning(), 0);
150 
151     EXPECT_THAT(mDeliveredCbs, IsEmpty());
152 }
153 
TEST_F(AppOpsSessionTests,endDeliveryRequest_PausedByCb)154 TEST_F(AppOpsSessionTests, endDeliveryRequest_PausedByCb) {
155     facadeSetAllowed(true);
156     initSession();
157     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
158     EXPECT_EQ(facadeGetRunning(), 1);
159     facadeTriggerChange(false);
160     EXPECT_EQ(facadeGetRunning(), 0);
161 
162     mAppOpsSession->endDeliveryRequest();
163     EXPECT_EQ(facadeGetRunning(), 0);
164 }
165 
TEST_F(AppOpsSessionTests,onPermittedFalse_Ongoing_Change)166 TEST_F(AppOpsSessionTests, onPermittedFalse_Ongoing_Change) {
167     facadeSetAllowed(true);
168     initSession();
169     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
170     EXPECT_EQ(facadeGetRunning(), 1);
171     facadeTriggerChange(false);
172     EXPECT_EQ(facadeGetRunning(), 0);
173     EXPECT_THAT(mDeliveredCbs, ElementsAreArray({false}));
174 }
175 
TEST_F(AppOpsSessionTests,onPermittedTrue_Ongoing_Change)176 TEST_F(AppOpsSessionTests, onPermittedTrue_Ongoing_Change) {
177     facadeSetAllowed(false);
178     initSession();
179     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
180     EXPECT_EQ(facadeGetRunning(), 0);
181     facadeTriggerChange(true);
182     EXPECT_EQ(facadeGetRunning(), 1);
183     EXPECT_THAT(mDeliveredCbs, ElementsAreArray({true}));
184 }
185 
TEST_F(AppOpsSessionTests,onPermittedTrue_Ongoing_Change_Spurious)186 TEST_F(AppOpsSessionTests, onPermittedTrue_Ongoing_Change_Spurious) {
187     facadeSetAllowed(false);
188     initSession();
189     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
190     EXPECT_EQ(facadeGetRunning(), 0);
191     facadeTriggerSpuriousChange(true);
192     EXPECT_EQ(facadeGetRunning(), 0);
193     EXPECT_THAT(mDeliveredCbs, IsEmpty());
194 }
195 
TEST_F(AppOpsSessionTests,onPermittedFalse_Ongoing_Same)196 TEST_F(AppOpsSessionTests, onPermittedFalse_Ongoing_Same) {
197     facadeSetAllowed(false);
198     initSession();
199     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
200     EXPECT_EQ(facadeGetRunning(), 0);
201     facadeTriggerSpuriousChange(false);
202     EXPECT_EQ(facadeGetRunning(), 0);
203 
204     EXPECT_THAT(mDeliveredCbs, IsEmpty());
205 }
206 
TEST_F(AppOpsSessionTests,onPermittedTrue_Ongoing_Same)207 TEST_F(AppOpsSessionTests, onPermittedTrue_Ongoing_Same) {
208     facadeSetAllowed(true);
209     initSession();
210     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
211     EXPECT_EQ(facadeGetRunning(), 1);
212     facadeTriggerSpuriousChange(true);
213     EXPECT_EQ(facadeGetRunning(), 1);
214 
215     EXPECT_THAT(mDeliveredCbs, IsEmpty());
216 }
217 
TEST_F(AppOpsSessionTests,onPermittedFalse_Paused_Change)218 TEST_F(AppOpsSessionTests, onPermittedFalse_Paused_Change) {
219     facadeSetAllowed(true);
220     initSession();
221     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
222     mAppOpsSession->endDeliveryRequest();
223 
224     EXPECT_EQ(facadeGetRunning(), 0);
225     facadeTriggerChange(false);
226     EXPECT_EQ(facadeGetRunning(), 0);
227     EXPECT_THAT(mDeliveredCbs, IsEmpty());
228 }
229 
TEST_F(AppOpsSessionTests,onPermittedTrue_Paused_Change)230 TEST_F(AppOpsSessionTests, onPermittedTrue_Paused_Change) {
231     facadeSetAllowed(false);
232     initSession();
233     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
234     mAppOpsSession->endDeliveryRequest();
235 
236     facadeTriggerChange(true);
237     EXPECT_EQ(facadeGetRunning(), 0);
238     EXPECT_THAT(mDeliveredCbs, IsEmpty());
239 }
240 
TEST_F(AppOpsSessionTests,dtor_Running)241 TEST_F(AppOpsSessionTests, dtor_Running) {
242     facadeSetAllowed(true);
243     initSession();
244     EXPECT_TRUE(mAppOpsSession->beginDeliveryRequest());
245     EXPECT_EQ(facadeGetRunning(), 1);
246 
247     // call dtor
248     mAppOpsSession.reset();
249     EXPECT_EQ(facadeGetRunning(), 0);
250 }
251 
TEST_F(AppOpsSessionTests,dtor_NotRunning)252 TEST_F(AppOpsSessionTests, dtor_NotRunning) {
253     facadeSetAllowed(false);
254     initSession();
255     EXPECT_FALSE(mAppOpsSession->beginDeliveryRequest());
256     EXPECT_EQ(facadeGetRunning(), 0);
257 
258     // call dtor
259     mAppOpsSession.reset();
260     EXPECT_EQ(facadeGetRunning(), 0);
261 }
262