• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021, 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 "CarPowerPolicyServer.h"
18 #include "SilentModeHandler.h"
19 
20 #include <android-base/chrono_utils.h>
21 #include <android-base/file.h>
22 #include <android-base/strings.h>
23 #include <gmock/gmock.h>
24 #include <utils/StrongPointer.h>
25 
26 #include <unistd.h>
27 
28 #include <cstring>
29 
30 namespace android {
31 namespace frameworks {
32 namespace automotive {
33 namespace powerpolicy {
34 
35 using ::aidl::android::frameworks::automotive::powerpolicy::BnCarPowerPolicyServer;
36 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy;
37 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicyFilter;
38 using ::aidl::android::frameworks::automotive::powerpolicy::ICarPowerPolicyChangeCallback;
39 using ::aidl::android::frameworks::automotive::powerpolicy::PowerComponent;
40 
41 using ::android::sp;
42 using ::android::base::ReadFileToString;
43 using ::android::base::Trim;
44 using ::android::base::WriteStringToFd;
45 using ::ndk::ScopedAStatus;
46 using ::testing::_;
47 
48 namespace {
49 
50 constexpr const char* kBootReasonNormal = "reboot,shell";
51 
52 constexpr int kMaxPollingAttempts = 5;
53 constexpr std::chrono::microseconds kPollingDelayUs = 50ms;
54 
55 }  // namespace
56 
57 namespace internal {
58 
59 class SilentModeHandlerPeer {
60 public:
SilentModeHandlerPeer(SilentModeHandler * handler)61     explicit SilentModeHandlerPeer(SilentModeHandler* handler) : mHandler(handler) {}
62 
~SilentModeHandlerPeer()63     ~SilentModeHandlerPeer() { mHandler->stopMonitoringSilentModeHwState(); }
64 
init()65     void init() {
66         mHandler->mSilentModeHwStateFilename = mFileSilentModeHwState.path;
67         mHandler->mKernelSilentModeFilename = mFileKernelSilentMode.path;
68         mHandler->init();
69     }
70 
injectBootReason(const std::string & bootReason)71     void injectBootReason(const std::string& bootReason) { mHandler->mBootReason = bootReason; }
72 
updateSilentModeHwState(bool isSilent)73     void updateSilentModeHwState(bool isSilent) {
74         WriteStringToFd(isSilent ? kValueSilentMode : kValueNonSilentMode,
75                         mFileSilentModeHwState.fd);
76     }
77 
readKernelSilentMode()78     std::string readKernelSilentMode() {
79         std::string value;
80         if (!ReadFileToString(mFileKernelSilentMode.path, &value)) {
81             return "";
82         }
83         return Trim(value);
84     }
85 
updateKernelSilentMode(bool isSilent)86     void updateKernelSilentMode(bool isSilent) { mHandler->updateKernelSilentMode(isSilent); }
87 
88 private:
89     SilentModeHandler* mHandler;
90     TemporaryFile mFileSilentModeHwState;
91     TemporaryFile mFileKernelSilentMode;
92 };
93 
94 }  // namespace internal
95 
96 class MockCarPowerPolicyServer : public ISilentModeChangeHandler, public BnCarPowerPolicyServer {
97 public:
98     MOCK_METHOD(ScopedAStatus, getCurrentPowerPolicy, (CarPowerPolicy * aidlReturn), (override));
99     MOCK_METHOD(ScopedAStatus, getPowerComponentState,
100                 (PowerComponent componentId, bool* aidlReturn), (override));
101     MOCK_METHOD(ScopedAStatus, registerPowerPolicyChangeCallback,
102                 (const std::shared_ptr<ICarPowerPolicyChangeCallback>& callback,
103                  const CarPowerPolicyFilter& filter),
104                 (override));
105     MOCK_METHOD(ScopedAStatus, unregisterPowerPolicyChangeCallback,
106                 (const std::shared_ptr<ICarPowerPolicyChangeCallback>& callback), (override));
107     MOCK_METHOD(void, notifySilentModeChange, (const bool silent), (override));
108 };
109 
110 class SilentModeHandlerTest : public ::testing::Test {
111 public:
SilentModeHandlerTest()112     SilentModeHandlerTest() {
113         carPowerPolicyServer = ::ndk::SharedRefBase::make<MockCarPowerPolicyServer>();
114     }
115 
116     std::shared_ptr<MockCarPowerPolicyServer> carPowerPolicyServer;
117 };
118 
TEST_F(SilentModeHandlerTest,TestRebootForForcedSilentMode)119 TEST_F(SilentModeHandlerTest, TestRebootForForcedSilentMode) {
120     SilentModeHandler handler(carPowerPolicyServer.get());
121     internal::SilentModeHandlerPeer handlerPeer(&handler);
122     handlerPeer.injectBootReason(kBootReasonForcedSilent);
123     handlerPeer.init();
124 
125     ASSERT_TRUE(handler.isSilentMode())
126             << "It should be silent mode when booting with forced silent mode";
127     EXPECT_CALL(*carPowerPolicyServer, notifySilentModeChange(_)).Times(0);
128 
129     handlerPeer.updateSilentModeHwState(/*isSilent=*/false);
130 
131     ASSERT_TRUE(handler.isSilentMode())
132             << "When booting with forced silent mode, silent mode should not change by HW state";
133 }
134 
TEST_F(SilentModeHandlerTest,TestRebootForForcedNonSilentMode)135 TEST_F(SilentModeHandlerTest, TestRebootForForcedNonSilentMode) {
136     SilentModeHandler handler(carPowerPolicyServer.get());
137     internal::SilentModeHandlerPeer handlerPeer(&handler);
138     handlerPeer.injectBootReason(kBootReasonForcedNonSilent);
139     handlerPeer.init();
140 
141     ASSERT_FALSE(handler.isSilentMode())
142             << "It should be non-silent mode when booting with forced non-silent mode";
143 
144     handlerPeer.updateSilentModeHwState(/*isSilent=*/true);
145 
146     ASSERT_FALSE(handler.isSilentMode()) << "When booting with forced non-silent mode, silent mode "
147                                             "should not change by HW state";
148 }
149 
TEST_F(SilentModeHandlerTest,TestUpdateKernelSilentMode)150 TEST_F(SilentModeHandlerTest, TestUpdateKernelSilentMode) {
151     SilentModeHandler handler(carPowerPolicyServer.get());
152     internal::SilentModeHandlerPeer handlerPeer(&handler);
153     handlerPeer.injectBootReason(kBootReasonNormal);
154     handlerPeer.init();
155 
156     handlerPeer.updateKernelSilentMode(true);
157 
158     ASSERT_EQ(handlerPeer.readKernelSilentMode(), kValueSilentMode)
159             << "Kernel silent mode file should have 1";
160 
161     handlerPeer.updateKernelSilentMode(false);
162 
163     ASSERT_EQ(handlerPeer.readKernelSilentMode(), kValueNonSilentMode)
164             << "Kernel silent mode file should have 0";
165 }
166 
167 }  // namespace powerpolicy
168 }  // namespace automotive
169 }  // namespace frameworks
170 }  // namespace android
171