
StatusTracker介绍
StatusTracker是Android15 Camera框架中用来协调Camera3各组件之间状态转换的类。
StatusTracker线程名:std::string("C3Dev-") + mId + "-Status"
Camera3 StatusTracker工作原理
StatusTracker实现批处理(状态转换)的基础
StatusTracker对组件(component)状态的跟踪和处理,主要围绕三个表一个线程来实现:
- 三个表
- mComponentName 用于记录注册的组件名字和跟踪id。
- mState 用于记录注册的组件状态。
- mPendingChangeQueue 用于记录组件pending StateChange(提交的某个组件的statechange, 待后续处理完成)。
- 一个工作线程
- threadLoop
首先,一个component通过addComponent()向StatusTracker注册跟踪,StatusTracker会根据当前注册情况为这个component分配一个trackId(mNextComponentId记录当前注册了多少component),并将这个component登记到mComponentName表,以默认IDLE的状态登记到mState表。
然后,一个component通过markComponentActive(trackId)或者makrComponentIdle(trackId, Fence)向StatusTracker提交一个状态转换(StateChange),StatusTracker将这个component的状态转换请求添加到mPendingChangeQueue。StatusTracker工作线程负责处理提交到mPendingChangeQueue的状态转换。
StatusTracker工作线程的6个状态
StatusTracker工作线程有6个状态,状态之间的转换如下

图1.StatusTracker工作线程状态转换图
StatusTracker的生与死由Camera3Device控制。Camera3Device::initializeCommonLocked()初始化基础内容时创建并启动这个StatusTracker工作线程;Camera3Device::disconnectImpl()主动调用requestExit(),将StatusTracker工作线程标记为dead, 系统Thread实现触发最终的StatusTracker工作线程退出。
StatusTracker处理一次状态转换可能有两种情况
- 跟踪的组件有变化。包括组件通过addComponent()/removeComponent()主动注册或注销,也包括状态转换处理后组件idle(idleFence)。
- 跟踪的组件状态有变化。组件通过markComponentX()主动标记状态。
StatusTracker工作线程相关的两个信号
从图1.StatusTracker工作线程状态转换图中,StatusTracker工作线程协作有两个信号:
- mPendingChangeSignal信号,是组件状态更改提交(尚未完成)的信号。组件主动注册/注销/标记状态会触发这个信号,Camera3Device结束StatusTracker工作线程也会发这个信号。
- mFlushCondition信号,是一批状态变更完成的信号。当所有的状态变更处理完会清空mPendingChangeQueue,并发送这个信号,表示StatusTracker已经冲刷完成。
StatusTracker工作线程处理状态转换
StatusTracker一次状态处理使分三步做的:
- 将mPendingChangeQueue中的各组件状态变更统一收集到mStateTransitions,同时更新跟踪状态表。
2.将状态变更通知给parent(这里也就是Camera3Device)
3.所有的pengding change处理完,标记tracker为flushed
代码如下:
StatusTracker收集组件状态转换(包括组件间中间状态转换)
cpp
sp<Camera3Device> parent;
198 {
199 Mutex::Autolock pl(mPendingLock);
200 Mutex::Autolock l(mLock);
201
202 // Collect all pending state updates and see if the device
203 // collectively transitions between idle and active for each one
204
//获取被跟踪组件的状态,优先获取到active状态的
//如果所有的组件都是idle状态,那么检查fence时间戳确定xx状态
205 // First pass for changed components or fence completions
206 ComponentState prevState = getDeviceStateLocked();
//疑问:组件状态和mDeviceState怎么达到一致?
//这里收集状态的切换, 有两种可能:active->idle, idle->active
207 if (prevState != mDeviceState) {
208 // Only collect changes to overall device state
209 mStateTransitions.add(prevState);
210 }
211 // For each pending component state update, check if we've transitioned
212 // to a new overall device state
213 for (size_t i = 0; i < mPendingChangeQueue.size(); i++) {
//一个状态转换动作
214 const StateChange &newState = mPendingChangeQueue[i];
//这个状态转换动作是哪个组件来做
215 ssize_t idx = mStates.indexOfKey(newState.id);
216 // Ignore notices for unknown components
217 if (idx >= 0) {
//更新这个组件的状态
218 // Update single component state
219 mStates.replaceValueAt(idx, newState.state);
//这是什么意思?
220 mIdleFence = Fence::merge(String8("idleFence"),
221 mIdleFence, newState.fence);
//检查被跟踪的组件状态
//收集状态切换
222 // .. and see if overall device state has changed
223 ComponentState newState = getDeviceStateLocked();
224 if (newState != prevState) {
225 mStateTransitions.add(newState);
226 }
227 prevState = newState;
228 }
229 }
//一次状态切换收集后,清空mPendingChangeQueue以进行下一次状态收集。
230 mPendingChangeQueue.clear();
231 mComponentsChanged = false;
232
233 // Store final state after all pending state changes are done with
234
//一次状态收集后,得到StatusTracker的状态
235 mDeviceState = prevState;
236 parent = mParent.promote();
237 }
StatusTracker将收集的状态转换通知给parent (Camera3Device)
cpp
if (mStateTransitions.size() > 0 && parent.get()) {
for (size_t i = 0; i < mStateTransitions.size(); i++) {
bool idle = (mStateTransitions[i] == IDLE);
ALOGV("Camera device is now %s", idle ? "idle" : "active");
parent->notifyStatus(idle);
}
}
mStateTransitions.clear();
StatusTracker代码实现中的几个点
cpp
//StatusTracker工作线程退出需要Camera3Device主动触发
//但是StatusTracker本质是Android Thread, 退出有一定的延时性。
//退出相关代码:
void StatusTracker::requestExit()
{
//First mark thread dead.
Thread::requestExit();
//Then exit any waits
mPendingChangeSignal.signal();
mFlushCondition.signal();
}
bool StatusTracker::threadLoop()
{
{
Mutex::Autolock pl(mPendinglock);
while (mPendingChangeQueueSize() == 0 && !mComponentsChanged) {
//等待pending change处理信号
res = mPendingChangeSignal.waitRelative(mPendingLock, kWaitDuration);
//线程退出
if (exitPending()) return false;
if (res != OK) {
if (res != TIMED_OUT) {
ALOGE("%s: Error waiting on state changes: %s (%d)",
__FUNCTION__, strerror(-res), res);
}
//TIMED_OUT is expected
break;
}
}
}
...
}