• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 "wake_lock_manager.h"
18 
19 #include <base/bind.h>
20 #include <base/files/file_util.h>
21 #include <base/format_macros.h>
22 #include <base/logging.h>
23 #include <base/strings/stringprintf.h>
24 #include <binder/IBinder.h>
25 #include <binderwrapper/binder_wrapper.h>
26 
27 namespace android {
28 namespace {
29 
30 // Paths to the sysfs lock and unlock files.
31 const char kLockPath[] = "/sys/power/wake_lock";
32 const char kUnlockPath[] = "/sys/power/wake_unlock";
33 
34 // Writes |data| to |path|, returning true on success or logging an error and
35 // returning false otherwise.
WriteToFile(const base::FilePath & path,const std::string & data)36 bool WriteToFile(const base::FilePath& path, const std::string& data) {
37   // This are sysfs "files" in real life, so it doesn't matter if we overwrite
38   // them or append to them, but appending makes it easier for tests to detect
39   // multiple writes when using real temporary files.
40   VLOG(1) << "Writing \"" << data << "\" to " << path.value();
41   if (!base::AppendToFile(path, data.data(), data.size())) {
42     PLOG(ERROR) << "Failed to write \"" << data << "\" to " << path.value();
43     return false;
44   }
45   return true;
46 }
47 
48 }  // namespace
49 
50 const char WakeLockManager::kLockName[] = "nativepowerman";
51 
Request(const std::string & tag,const std::string & package,uid_t uid)52 WakeLockManager::Request::Request(const std::string& tag,
53                                   const std::string& package,
54                                   uid_t uid)
55     : tag(tag),
56       package(package),
57       uid(uid) {}
58 
59 WakeLockManager::Request::Request(const Request& request) = default;
60 
Request()61 WakeLockManager::Request::Request() : uid(-1) {}
62 
WakeLockManager()63 WakeLockManager::WakeLockManager()
64     : lock_path_(kLockPath),
65       unlock_path_(kUnlockPath) {}
66 
~WakeLockManager()67 WakeLockManager::~WakeLockManager() {
68   while (!requests_.empty())
69     RemoveRequest(requests_.begin()->first);
70 }
71 
Init()72 bool WakeLockManager::Init() {
73   if (!base::PathIsWritable(lock_path_) ||
74       !base::PathIsWritable(unlock_path_)) {
75     LOG(ERROR) << lock_path_.value() << " and/or " << unlock_path_.value()
76                << " are not writable";
77     return false;
78   }
79   return true;
80 }
81 
AddRequest(sp<IBinder> client_binder,const std::string & tag,const std::string & package,uid_t uid)82 bool WakeLockManager::AddRequest(sp<IBinder> client_binder,
83                                  const std::string& tag,
84                                  const std::string& package,
85                                  uid_t uid) {
86   const bool new_request = !requests_.count(client_binder);
87   LOG(INFO) << (new_request ? "Adding" : "Updating") << " request for binder "
88             << client_binder.get() << ": tag=\"" << tag << "\""
89             << " package=\"" << package << "\" uid=" << uid;
90 
91   const bool first_request = requests_.empty();
92 
93   if (new_request) {
94     if (!BinderWrapper::Get()->RegisterForDeathNotifications(
95             client_binder,
96             base::Bind(&WakeLockManager::HandleBinderDeath,
97                        base::Unretained(this), client_binder))) {
98       return false;
99     }
100   }
101   requests_[client_binder] = Request(tag, package, uid);
102 
103   if (first_request && !WriteToFile(lock_path_, kLockName))
104     return false;
105 
106   return true;
107 }
108 
RemoveRequest(sp<IBinder> client_binder)109 bool WakeLockManager::RemoveRequest(sp<IBinder> client_binder) {
110   LOG(INFO) << "Removing request for binder " << client_binder.get();
111 
112   if (!requests_.erase(client_binder)) {
113     LOG(WARNING) << "Ignoring removal request for unknown binder "
114                  << client_binder.get();
115     return false;
116   }
117   BinderWrapper::Get()->UnregisterForDeathNotifications(client_binder);
118 
119   if (requests_.empty() && !WriteToFile(unlock_path_, kLockName))
120     return false;
121 
122   return true;
123 }
124 
HandleBinderDeath(sp<IBinder> binder)125 void WakeLockManager::HandleBinderDeath(sp<IBinder> binder) {
126   LOG(INFO) << "Received death notification for binder " << binder.get();
127   RemoveRequest(binder);
128 }
129 
130 }  // namespace android
131