1 /* 2 * Copyright (C) 2010 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 "unclean_shutdown_collector.h" 18 19 #include <base/files/file_util.h> 20 #include <base/logging.h> 21 22 static const char kUncleanShutdownFile[] = 23 "/var/lib/crash_reporter/pending_clean_shutdown"; 24 25 // Files created by power manager used for crash reporting. 26 static const char kPowerdTracePath[] = "/var/lib/power_manager"; 27 // Presence of this file indicates that the system was suspended 28 static const char kPowerdSuspended[] = "powerd_suspended"; 29 30 using base::FilePath; 31 32 UncleanShutdownCollector::UncleanShutdownCollector() 33 : unclean_shutdown_file_(kUncleanShutdownFile), 34 powerd_trace_path_(kPowerdTracePath), 35 powerd_suspended_file_(powerd_trace_path_.Append(kPowerdSuspended)) { 36 } 37 38 UncleanShutdownCollector::~UncleanShutdownCollector() { 39 } 40 41 bool UncleanShutdownCollector::Enable() { 42 FilePath file_path(unclean_shutdown_file_); 43 base::CreateDirectory(file_path.DirName()); 44 if (base::WriteFile(file_path, "", 0) != 0) { 45 LOG(ERROR) << "Unable to create shutdown check file"; 46 return false; 47 } 48 return true; 49 } 50 51 bool UncleanShutdownCollector::DeleteUncleanShutdownFiles() { 52 if (!base::DeleteFile(FilePath(unclean_shutdown_file_), false)) { 53 LOG(ERROR) << "Failed to delete unclean shutdown file " 54 << unclean_shutdown_file_; 55 return false; 56 } 57 // Delete power manager state file if it exists. 58 base::DeleteFile(powerd_suspended_file_, false); 59 return true; 60 } 61 62 bool UncleanShutdownCollector::Collect() { 63 FilePath unclean_file_path(unclean_shutdown_file_); 64 if (!base::PathExists(unclean_file_path)) { 65 return false; 66 } 67 LOG(WARNING) << "Last shutdown was not clean"; 68 if (DeadBatteryCausedUncleanShutdown()) { 69 DeleteUncleanShutdownFiles(); 70 return false; 71 } 72 DeleteUncleanShutdownFiles(); 73 74 if (is_feedback_allowed_function_()) { 75 count_crash_function_(); 76 } 77 return true; 78 } 79 80 bool UncleanShutdownCollector::Disable() { 81 LOG(INFO) << "Clean shutdown signalled"; 82 return DeleteUncleanShutdownFiles(); 83 } 84 85 bool UncleanShutdownCollector::DeadBatteryCausedUncleanShutdown() { 86 // Check for case of battery running out while suspended. 87 if (base::PathExists(powerd_suspended_file_)) { 88 LOG(INFO) << "Unclean shutdown occurred while suspended. Not counting " 89 << "toward unclean shutdown statistic."; 90 return true; 91 } 92 return false; 93 } 94