1 /*
2  * Copyright (C) 2017 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 "IotBootAnimation"
18 
19 #include <base/files/file_util.h>
20 #include <binder/IPCThreadState.h>
21 #include <binder/IServiceManager.h>
22 #include <binder/ProcessState.h>
23 #include <cutils/properties.h>
24 #include <sys/resource.h>
25 #include <utils/Log.h>
26 #include <utils/threads.h>
27 #include <BootAnimation.h>
28 
29 #include "BootAction.h"
30 #include "BootAnimationUtil.h"
31 #include "BootParameters.h"
32 
33 using namespace android;
34 
35 // Create a typedef for readability.
36 typedef android::BootAnimation::Animation Animation;
37 
38 namespace {
39 
40 constexpr const char* kDefaultLibName = "libbootaction.so";
41 
42 class BootActionAnimationCallbacks : public android::BootAnimation::Callbacks {
43 public:
BootActionAnimationCallbacks(std::unique_ptr<BootParameters> bootParameters)44     BootActionAnimationCallbacks(std::unique_ptr<BootParameters> bootParameters)
45         : mBootParameters(std::move(bootParameters)) {}
46 
init(const Vector<Animation::Part> &)47     void init(const Vector<Animation::Part>&) override {
48         std::string library_path("/oem/lib/");
49 
50         // This value is optionally provided by the user and will be written to
51         // /oem/oem.prop.
52         char property[PROP_VALUE_MAX] = {0};
53         property_get("ro.oem.bootactions.lib", property, kDefaultLibName);
54         library_path += property;
55 
56         if (!::base::PathExists(::base::FilePath(library_path))) {
57             ALOGI("Skipping boot actions: %s does not exist", library_path.c_str());
58             return;
59         }
60 
61         mBootAction = new BootAction();
62         if (!mBootAction->init(library_path, mBootParameters)) {
63             mBootAction = nullptr;
64         }
65     };
66 
playPart(int partNumber,const Animation::Part &,int playNumber)67     void playPart(int partNumber, const Animation::Part&, int playNumber) override {
68         if (mBootAction != nullptr) {
69             mBootAction->startPart(partNumber, playNumber);
70         }
71     };
72 
shutdown()73     void shutdown() override {
74         if (mBootAction != nullptr) {
75             // If we have a bootaction we want to wait until we are actually
76             // told to shut down. If the animation exits early keep the action
77             // running.
78             char value[PROPERTY_VALUE_MAX] = {0};
79             for (int exitRequested = 0; exitRequested == 0; ) {
80                 property_get("service.bootanim.exit", value, "0");
81                 exitRequested = atoi(value);
82 
83                 // Poll value at 10hz.
84                 if (exitRequested == 0) {
85                   usleep(100000);
86                 }
87             }
88 
89             mBootAction->shutdown();
90             // Give it two seconds to shut down.
91             sleep(2);
92             mBootAction = nullptr;
93         }
94     };
95 
96 private:
97     std::unique_ptr<BootParameters> mBootParameters;
98     sp<BootAction> mBootAction = nullptr;
99 };
100 
101 }  // namespace
102 
main()103 int main() {
104     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
105 
106     // Clear our params for next boot no matter what.
107     std::unique_ptr<BootParameters> bootParameters(new BootParameters());
108 
109     if (bootAnimationDisabled()) {
110         ALOGI("boot animation disabled");
111         return 0;
112     }
113 
114     waitForSurfaceFlinger();
115 
116     sp<ProcessState> proc(ProcessState::self());
117     ProcessState::self()->startThreadPool();
118 
119     bool isSilentBoot = bootParameters->isSilentBoot();
120     sp<BootActionAnimationCallbacks> callbacks =
121         new BootActionAnimationCallbacks(std::move(bootParameters));
122 
123     // On silent boot, animations aren't displayed.
124     if (isSilentBoot) {
125         callbacks->init({});
126     } else {
127         sp<BootAnimation> boot = new BootAnimation(callbacks);
128     }
129 
130     IPCThreadState::self()->joinThreadPool();
131     return 0;
132 }
133