1 /* 2 * Copyright (C) 2020 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 "apexd" 18 19 #include "apexd_lifecycle.h" 20 21 #include <android-base/logging.h> 22 #include <android-base/properties.h> 23 24 #include "apexd_utils.h" 25 26 using android::base::GetProperty; 27 using android::base::Result; 28 using android::base::WaitForProperty; 29 30 namespace android { 31 namespace apex { 32 33 bool ApexdLifecycle::IsBooting() { 34 auto status = GetProperty(kApexStatusSysprop, ""); 35 return status != kApexStatusReady && status != kApexStatusActivated; 36 } 37 38 void ApexdLifecycle::WaitForBootStatus( 39 Result<void> (&revert_fn)(const std::string&, const std::string&)) { 40 while (!boot_completed_) { 41 // Check for change in either crashing property or sys.boot_completed 42 // Wait for updatable_crashing property change for most of the time 43 // (arbitrary 30s), briefly check if boot has completed successfully, 44 // if not continue waiting for updatable_crashing. 45 // We use this strategy so that we can quickly detect if an updatable 46 // process is crashing. 47 if (WaitForProperty("sys.init.updatable_crashing", "1", 48 std::chrono::seconds(30))) { 49 auto name = GetProperty("sys.init.updatable_crashing_process_name", ""); 50 LOG(ERROR) << "Native process '" << (name.empty() ? "[unknown]" : name) 51 << "' is crashing. Attempting a revert"; 52 auto result = revert_fn(name, ""); 53 if (!result.ok()) { 54 LOG(ERROR) << "Revert failed : " << result.error(); 55 break; 56 } else { 57 // This should never be reached, since revert_fn should've rebooted a 58 // device. But if for some reason we end up here, let's reboot it 59 // manually. 60 LOG(ERROR) << "Active sessions were reverted, but reboot wasn't " 61 "triggered. Rebooting manually"; 62 Reboot(); 63 return; 64 } 65 } 66 } 67 } 68 69 void ApexdLifecycle::MarkBootCompleted() { boot_completed_ = true; } 70 71 } // namespace apex 72 } // namespace android 73