Home | History | Annotate | Download | only in daemon
      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.
     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 
     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 
     61 WakeLockManager::Request::Request() : uid(-1) {}
     62 
     63 WakeLockManager::WakeLockManager()
     64     : lock_path_(kLockPath),
     65       unlock_path_(kUnlockPath) {}
     66 
     67 WakeLockManager::~WakeLockManager() {
     68   while (!requests_.empty())
     69     RemoveRequest(requests_.begin()->first);
     70 }
     71 
     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 
     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 
    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 
    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