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 #include "chre/platform/power_control_manager.h" 18 19 #include "chre/platform/slpi/power_control_util.h" 20 #include "chre/platform/slpi/see/island_vote_client.h" 21 #include "chre/platform/system_time.h" 22 #include "chre/util/lock_guard.h" 23 24 namespace chre { 25 26 PowerControlManagerBase::PowerControlManagerBase() : mHostIsAwake(true) { 27 #ifdef CHRE_THREAD_UTIL_ENABLED 28 sns_client_create_thread_utilization_client(&mThreadUtilClient); 29 #endif // CHRE_THREAD_UTIL_ENABLED 30 } 31 32 PowerControlManagerBase::~PowerControlManagerBase() { 33 #ifdef CHRE_THREAD_UTIL_ENABLED 34 sns_client_remove_thread_utilization_client(mThreadUtilClient); 35 #endif // CHRE_THREAD_UTIL_ENABLED 36 } 37 38 bool PowerControlManagerBase::voteBigImage(bool bigImage) { 39 return IslandVoteClientSingleton::get()->voteBigImage(bigImage); 40 } 41 42 void PowerControlManagerBase::onHostWakeSuspendEvent(bool awake) { 43 if (mHostIsAwake != awake) { 44 mHostIsAwake = awake; 45 46 if (!awake) { 47 EventLoopManagerSingleton::get() 48 ->getHostCommsManager() 49 .resetBlameForNanoappHostWakeup(); 50 } 51 52 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 53 mHostIsAwake ? CHRE_EVENT_HOST_AWAKE : CHRE_EVENT_HOST_ASLEEP, 54 nullptr /* eventData */, nullptr /* freeCallback */); 55 56 #ifdef CHRE_AUDIO_SUPPORT_ENABLED 57 if (awake) { 58 auto callback = [](uint16_t /* eventType */, void * /* eventData*/) { 59 EventLoopManagerSingleton::get() 60 ->getAudioRequestManager() 61 .getPlatformAudio() 62 .onHostAwake(); 63 }; 64 65 EventLoopManagerSingleton::get()->deferCallback( 66 SystemCallbackType::AudioHandleHostAwake, nullptr, callback); 67 } 68 #endif // CHRE_AUDIO_SUPPORT_ENABLED 69 } 70 } 71 72 void PowerControlManager::postEventLoopProcess(size_t numPendingEvents) { 73 #ifdef CHRE_THREAD_UTIL_ENABLED 74 // Although this execution point does not actually represent the start 75 // of the CHRE thread's activity, we only care about cases where the 76 // CHRE's event queue is highly backlogged for voting higher clock rates. 77 if (mIsThreadIdle && numPendingEvents != 0) { 78 sns_client_thread_utilization_start(mThreadUtilClient); 79 mIsThreadIdle = false; 80 } else if (!mIsThreadIdle) { 81 // Update the time profile as frequently as possible so that clock updates 82 // are not deferred until all events are processed. 83 sns_client_thread_utilization_stop(mThreadUtilClient); 84 if (numPendingEvents != 0) { 85 sns_client_thread_utilization_start(mThreadUtilClient); 86 } else { 87 mIsThreadIdle = true; 88 } 89 } 90 #endif // CHRE_THREAD_UTIL_ENABLED 91 92 if (numPendingEvents == 0 && !slpiInUImage()) { 93 voteBigImage(false /* bigImage */); 94 } 95 } 96 97 bool PowerControlManager::hostIsAwake() { 98 return mHostIsAwake; 99 } 100 101 } // namespace chre 102