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 "halstate.h" 18 HalState()19HalState::HalState() : mState(State::Constructed) { 20 } 21 init()22bool HalState::init() { 23 // Ensure that checking the state and waiting on the condition is atomic. 24 std::unique_lock<std::mutex> lock(mStateMutex); 25 26 if (mState != State::Stopped && mState != State::Constructed) { 27 // We can only initialize when freshly constructed or stopped 28 return false; 29 } 30 if (mInfo) { 31 // We are in the correct state but our info object is still allocated. 32 // This is a logic error somewhere and should not happen. 33 return false; 34 } 35 auto info = std::make_unique<Info>(); 36 if (info->init()) { 37 // Only store the info object to keep it alive if init succeeded. 38 // Otherwise we're going to remain in the previous state and having an 39 // uninitialized info object around will cause inconsistency. 40 mInfo = std::move(info); 41 mState = State::Initialized; 42 return true; 43 } 44 // If we failed to initalize we remain in the same state. 45 return false; 46 } 47 stop(StopHandler stopHandler)48bool HalState::stop(StopHandler stopHandler) { 49 { 50 // Ensure atomicity in checking and setting state 51 std::unique_lock<std::mutex> lock(mStateMutex); 52 53 if (mState == State::Stopping || mState == State::Stopped) { 54 // Already stopping or stopped, nothing to do 55 return false; 56 } 57 if (mState != State::Running) { 58 // Make sure there is no info object anymore. It should never exist 59 // in the stopped state. 60 mInfo.reset(); 61 // If we're neither stopping, stopped nor running then we can't stop 62 // again. It seems that sometimes the client expects to be able to 63 // call this when initialized or constructed so we'll set the state 64 // to stopped. We have to return false to prevent the caller from 65 // waiting for the callback though. Calling the callback here from 66 // the same thread that called stop could cause a deadlock. 67 mState = State::Stopped; 68 return false; 69 } 70 mState = State::Stopping; 71 } 72 mInfo->stop(std::bind(&HalState::onStop, this, stopHandler)); 73 // We have now requested the stop, we'll change state in the stop handler 74 // when it's called. 75 return true; 76 } 77 eventLoop()78bool HalState::eventLoop() { 79 { 80 // Atomically check and set state to running 81 std::unique_lock<std::mutex> lock(mStateMutex); 82 if (mState != State::Initialized || !mInfo) { 83 return false; 84 } 85 mState = State::Running; 86 } 87 mInfo->eventLoop(); 88 return true; 89 } 90 info()91Info* HalState::info() { 92 return mInfo.get(); 93 } 94 onStop(StopHandler stopHandler)95void HalState::onStop(StopHandler stopHandler) { 96 stopHandler(); 97 mInfo.reset(); 98 99 std::unique_lock<std::mutex> lock(mStateMutex); 100 mState = State::Stopped; 101 } 102 103