「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
在开发者模式中有一个显示刷新频率的开关,打开后在手机系统的左上角会绘制一个当前屏幕刷新频率的数字,那么它是如何来实现的呢?
开发者模式中,显示刷新屏幕开关的设定应是在ShowRefreshRatePreferenceController.java文件中进行控制的,因此,我们从此处开始分析下显示刷新率逻辑。
分析Settings应用的话,应该明确在继承自DeveloperOptionsPreferenceController类的对象在初始化的时候,应是首先调用其单参(Context类)构造函数,因此
static final String SURFACE_FLINGER_SERVICE_KEY = "SurfaceFlinger";
public ShowRefreshRatePreferenceController(Context context) {
super(context);
// 获取SurfaceFlinger服务
mSurfaceFlinger = ServiceManager.getService(SURFACE_FLINGER_SERVICE_KEY);
}
可以看到,此处主要是通过ServiceManager来获取到SurfaceFlinger服务
此后,当我们切换显示刷新屏幕的菜单的时候,会调用其onPreferenceChange函数,因此
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// 当前设置的开关的值
final boolean isEnabled = (Boolean) newValue;
// 写入显示屏幕刷新事件给到SurfaceFlinger服务
// 并更新当前显示刷新率的菜单开关
writeShowRefreshRateSetting(isEnabled);
return true;
}
@VisibleForTesting
void writeShowRefreshRateSetting(boolean isEnabled) {
try {
if (mSurfaceFlinger != null) {
// 1. SurfaceFlinger通信并传递信息
final Parcel data = Parcel.obtain();
// 设置interface token为”android.os.ISurfaceComposer”
data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY);
// 设置信息
final int showRefreshRate = isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF;
data.writeInt(showRefreshRate);
// binder机制,调用SurfaceFlinger的transact函数
// 注意,此处由于不需要有Binder反馈,因此此处reply设置为null
// 传递的code为1034
mSurfaceFlinger.transact(SURFACE_FLINGER_CODE, data,
null /* reply */, 0 /* flags */);
data.recycle();
}
}
// .....catch异常,省略
// 2. 更新当前的显示屏幕刷新菜单开关
updateShowRefreshRateSetting();
}
因此
SurfaceFlinger通信并传递信息
由上述的代码分析可知,最终会调用SurfaceFlinger的transact函数,因此
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
// ......其他条件均不满足,会进入default分支
default:
// 调用SurfaceFlinger的onTransact函数
err = onTransact(code, data, reply, flags);
break;
}
// ...... 此处为不走的代码,省略
return err;
}
最终会调用到onTransact函数,且传递的code为1034
status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
status_t credentialCheck = CheckTransactCodeCredentials(code);
if (credentialCheck != OK) {
return credentialCheck;
}
status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
// 判断interface token是否是android.os.ISurfaceComposer
CHECK_INTERFACE(ISurfaceComposer, data, reply);
// ...... 获取调用的主体是否具有system权限,
// 且是否有android.permission.HARDWARE_TEST权限
int n;
switch (code) {
// ......无关的分支,省略
case 1034: {
// 获取此前设定的数据信息,打开 or 关闭
switch (n = data.readInt32()) {
case 0:
case 1:
// 调用打开或者关闭屏幕刷新率函数
enableRefreshRateOverlay(static_cast<bool>(n));
break;
default: {
Mutex::Autolock lock(mStateLock);
reply->writeBool(mRefreshRateOverlay != nullptr);
}
}
return NO_ERROR;
}
// ...... 无关分支,省略
}
}
return err;
}
调用enableRefreshRateOverlay函数处理
void SurfaceFlinger::enableRefreshRateOverlay(bool enable) {
// 1. 生成schedule函数返回值指针
static_cast<void>(schedule([=] {
// 2. 初始化指向RefresnRateOverlay对象的指针
// 这边可以看到,当enable为false的时候,即关闭显示屏幕刷新率的时候,直接不初始化
// 只有在enable为true的时候,即打开显示屏幕刷新率的时候才会初始化对象
std::unique_ptr<RefreshRateOverlay> overlay;
if (enable) {
overlay = std::make_unique<RefreshRateOverlay>(*this);
}
{
Mutex::Autolock lock(mStateLock);
// Destroy the layer of the current overlay, if any, outside the lock.
mRefreshRateOverlay.swap(overlay);
// 当关闭刷新屏幕刷新率的时候,直接退出不做处理
// 打开开关的情况,跳过这边代码,进入下个分析阶段
if (!mRefreshRateOverlay) return;
// 3. 获取当前系统的默认显示设备DeviceDisplay对象,并且设置其显示区域
if (const auto display = getDefaultDisplayDeviceLocked()) {
mRefreshRateOverlay->setViewport(display->getSize());
}
// 4. RefreshRateOverlay的刷新率变化函数
mRefreshRateOverlay->changeRefreshRate(
mRefreshRateConfigs->getCurrentRefreshRate());
}
}));
}
这段代码可以看到,当关闭显示屏幕刷新率的时候,直接不做任何处理并退出,只有当打开显示屏幕刷新率的时候,才会做其他处理,此处我们只分析打开显示屏幕刷新率的情况,因此,按照以下步骤分析
schedule函数的具体实现
首先看这个函数的定义和实现
template <typename F, typename T>
inline std::future<T> SurfaceFlinger::schedule(F&& f) {
// 生成一个std::pair结构体对象,第一个参数为Task对象,
// 第二个参数为Task对象的mTask封装的函数,即传入参数
auto [task, future] = makeTask(std::move(f));
// 发送消息处理
// 最终会调用task指针对象的handleMessage函数,此处不做分析,有兴趣可以自行看下
mEventQueue->postMessage(std::move(task));
// 返回函数指针
return std::move(future);
}
MessageQueue.h
template <typename F>
inline auto makeTask(F&& f) {
// 初始化Task指针对象
sp<Task<F>> task = new Task<F>(std::move(f));
// 生成pair,第一个参数为task对象,第二个参数为其mTask封装的函数指针
return std::make_pair(task, task->mTask.get_future());
}
template <typename F>
class Task : public MessageHandler {
template <typename G>
friend auto makeTask(G&&);
explicit Task(F&& f) : mTask(std::move(f)) {}
void handleMessage(const Message&) override { mTask(); }
using T = std::invoke_result_t<F>;
std::packaged_task<T()> mTask;
};
可以看到,这段代码最终的结果是schedule函数中的参数函数指针对应的函数被运行
初始化指向RefresnRateOverlay对象的指针
初始化直接使用其构造函数
RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger)
: mFlinger(flinger), mClient(new Client(&mFlinger)) {
createLayer();
primeCache();
}
从这边可以看到,首先初始化一个指向Client对象的指针,然后调用createLayer函数创建一个Surface,最后调用primeCache渲染
当然我们重点看下后面两个步骤
RefreshRateOverlay::createLayer
bool RefreshRateOverlay::createLayer() {
// 调用SurfaceFlinger::createLayer函数初始化一个Layer指针对象
// 注意,此处的Layer的大小,这边传入的是
// static constexpr uint32_t DIGIT_HEIGHT = 100;
// static constexpr uint32_t BUFFER_HEIGHT = DIGIT_HEIGHT;
// static constexpr uint32_t BUFFER_WIDTH = 3 * DIGIT_WIDTH + 2 * DIGIT_SPACE;
// static constexpr uint32_t DIGIT_WIDTH = 64;
// static constexpr uint32_t DIGIT_SPACE = 16;
const status_t ret =
mFlinger.createLayer(String8("RefreshRateOverlay"), mClient,
SevenSegmentDrawer::getWidth(), SevenSegmentDrawer::getHeight(),
PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState, LayerMetadata(),
&mIBinder, &mGbp, nullptr);
// ...... 容错判断,此处省略
Mutex::Autolock _l(mFlinger.mStateLock);
// 获取刚刚创建的Layer指针对象
mLayer = mClient->getLayerUser(mIBinder);
// 设置Layer的帧率
mLayer->setFrameRate(Layer::FrameRate(0, Layer::FrameRateCompatibility::NoVote));
// setting Layer's Z requires resorting layersSortedByZ
// 设置Layer的z轴
ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer);
if (mLayer->setLayer(INT32_MAX - 2) && idx >= 0) {
mFlinger.mCurrentState.layersSortedByZ.removeAt(idx);
mFlinger.mCurrentState.layersSortedByZ.add(mLayer);
}
return true;
}
这边
首先使用SurfaceFlinger::createLayer初始化一个Layer指针对象
status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
uint32_t h, PixelFormat format, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp,
const sp<IBinder>& parentHandle,
const sp<Layer>& parentLayer,
uint32_t* outTransformHint) {
// ...... 错误判断代码,省略
status_t result = NO_ERROR;
sp<Layer> layer;
// 获取Layer的名称
std::string uniqueName = getUniqueLayerName(name.string());
bool primaryDisplayOnly = false;
// ...... 判断Window Type,此处不会进入,省略
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
// ...... 不会进入,此处省略
case ISurfaceComposerClient::eFXSurfaceBufferState:
result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
std::move(metadata), handle, &layer);
break;
// ...... 不会进入,此处省略
}
// ...... 错误判断代码,省略
// 判断是否有权限
bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
// 添加到mLayers集合
result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
addToCurrentState, outTransformHint);
if (result != NO_ERROR) {
return result;
}
mInterceptor->saveSurfaceCreation(layer);
// 通知绘制
setTransactionFlags(eTransactionNeeded);
return result;
}
在这边
首先通过createBufferStateLayer函数创建一个Layer对象
status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, std::string name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<Layer>* outLayer) {
// 整合参数
LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
args.textureName = getNewTexture();
// 创建指向BufferStateLayer对象的指针
sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
// 获取Layer对应的索引,注意,此处是给传入参数handle赋值
*handle = layer->getHandle();
// 赋值操作,注意是令传入参数outLayer指向刚刚创建的BufferStateLayer对象
*outLayer = layer;
return NO_ERROR;
}
sp<BufferStateLayer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
// 初始化一个指向BufferStateLayer的指针
return new BufferStateLayer(args);
}
BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
: BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
// 设置BufferStateLayer对象的参数
mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
}
如上,会初始化一个指向BufferStateLayer对象的指针
Layer::onFirstRef
在此处,有必要看下BufferStateLayer的家族
classDiagram
Layer <|-- BufferLayer
BufferLayer <|-- BufferStateLayer
Layer : +sp<SurfaceFlinger> mFlinger
Layer : +sp<Client> mClientRef
Layer : +onFirstRefs()
因此,在BufferStateLayer指针对象初始化的时候,需要调用其onFirstRefs函数,从而从继承关系中可以看到最终会调用Layer::onFirstRefs函数,也即
void Layer::onFirstRef() {
mFlinger->onLayerFirstRef(this);
}
void SurfaceFlinger::onLayerFirstRef(Layer* layer) {
// 创建一个Layer对象,在SurfaceFlinger中的Layer数量要加1
mNumLayers++;
// 调用Scheduler的registerLayer函数,注册Layer
mScheduler->registerLayer(layer);
}
void Scheduler::registerLayer(Layer* layer) {
if (!mLayerHistory) return;
// 这边是获取系统支持的最小屏幕刷新率以及最大屏幕刷新率
// 这边的RefreshRateConfigs对象是在系统启动之后,从HwComposer中获取到的RefreshRateConfig
const auto minFps = mRefreshRateConfigs.getMinRefreshRate().getFps();
const auto maxFps = mRefreshRateConfigs.getMaxRefreshRate().getFps();
// Layer在创建的时候,window type未设置,值为0
if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) {
// ......此处无法进入,省略
} else if (!mUseContentDetection) {
// If the content detection feature is off, all layers are registered at Max.
// We still keep the layer history, since we use it for other features
// (like Frame Rate API), so layers still need to be registered.
// 主要通过LayerHistoryV2对象的registerLayer函数,
// 初始化LayerInfo对象添加到mLayerInfos中,
// 并设定LayerInfo的类型为scheduler::LayerHistory::LayerVoteType::Max
mLayerHistory->registerLayer(layer, minFps, maxFps,
scheduler::LayerHistory::LayerVoteType::Max);
}
// ......else分支无法进入,省略
}
可见,在创建完Layer对象后,均需要在Scheduler中对这些Layer的信息进行注册
SurfaceFlinger::addClientLayer
result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
addToCurrentState, outTransformHint);
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
const sp<IBinder>& parentHandle,
const sp<Layer>& parentLayer, bool addToCurrentState,
uint32_t* outTransformHint) {
// add this layer to the current state list
{
Mutex::Autolock _l(mStateLock);
sp<Layer> parent;
// ...... 判断函数无法进入,省略
parent = parentLayer;
// ...... 判错机制,省略(当Layer数量大于4096的时候,提示NO_MOMERY)
// 添加到Local binder token
mLayersByLocalBinderToken.emplace(handle->localBinder(), lbc);
if (parent == nullptr && addToCurrentState) {
mCurrentState.layersSortedByZ.add(lbc);
}
// ...... 无法走入代码,省略
// 此处会根据默认系统的变化参数,对当前的Layer进行对应的处理
if (const auto display = getDefaultDisplayDeviceLocked()) {
lbc->updateTransformHint(display->getTransformHint());
}
// ...... 无法进入代码,省略
mLayersAdded = true;
}
// attach this layer to the client
// 将当前的Layer的索引handle和对应的Layer组成键值对,添加到Client::mLayers
client->attachLayer(handle, lbc);
return NO_ERROR;
}
总结
此处通过SurfaceFlinger::createLayer函数初始化了一个BufferStateLayer指针对象,通过Layer::onFirstRef函数将刚创建的BufferStateLayer对象注册到LayerHistory中,最后通过SurfaceFlinger::addClientLayer函数,将初始化的BufferStateLayer添加到Client::mLayers,且对BufferStateLayer对象作出系统变换带来的一些变动
BufferStateLayer配置
在创建完成BufferStateLayer之后,会对这个Layer进行一些必要的设置,设置这个Layer图层在屏幕的最上方,即z轴的较大值(INT32_MAX – 2)
RefreshRateOverlay::primeCache
void RefreshRateOverlay::primeCache() {
// 这边会从RefreshRateConfigs中获取到所有支持的刷新率配置,
// 这些数据是在SurfaceFlinger在初始化的过程中,从HardwareComposer中获取到的
auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
// 若系统显示设备只支持一种系统刷新率,则直接获取其刷新率数值
// SevenSegmentDrawer::drawNumber函数会根据对应的数据和信息将对应的buffer数据写入到初始化的GraphicBuffer中
// 并且将刷新率和SevenSegmentDrawer::drawNumber获取到的GraphicBuffer作为键值对存储在mBufferCache中
if (allRefreshRates.size() == 1) {
auto fps = allRefreshRates.begin()->second->getFps();
half4 color = {LOW_FPS_COLOR, ALPHA};
mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
return;
}
// 若系统显示设备支持的屏幕刷新率不止一种,则对其进行相对应的处理
std::vector<uint32_t> supportedFps;
supportedFps.reserve(allRefreshRates.size());
for (auto& [ignored, refreshRate] : allRefreshRates) {
supportedFps.push_back(refreshRate->getFps());
}
// 需要先将刷新率按照刷新率大小来排序
std::sort(supportedFps.begin(), supportedFps.end());
const auto mLowFps = supportedFps[0];
const auto mHighFps = supportedFps[supportedFps.size() - 1];
// 根据当前的刷新率来生成对应的颜色,并使用SeventSegmentDrawer::drawNumber函数来分别
// 生成对应的GraphicBuffer,并且和其对应的屏幕刷新率组成键值对添加到mBufferCache中
for (auto fps : supportedFps) {
const auto fpsScale = float(fps - mLowFps) / (mHighFps - mLowFps);
half4 color;
color.r = HIGH_FPS_COLOR.r * fpsScale + LOW_FPS_COLOR.r * (1 - fpsScale);
color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale);
color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale);
color.a = ALPHA;
mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
}
}
总结
通过如上的代码可知,在初始化RefreshRateOverlay指针对象的时候,会
1.通过SurfaceFlinger的createLayer函数创建对应的BufferStateLayer图层,并且添加到Client::mLayers中进行管理
2.创建每个显示设备支持屏幕刷新率对应的GraphicBuffer对象(并绘制对应的屏幕上需要显示的视图),并添加到mBufferCache中
获取系统默认显示设备对象,并设置其显示区域
调用代码如下
// 这边会调用getDefaultDisplayDeviceLocked函数来获取默认的显示设备DisplayDevice对象
// 这个对象在SurfaceFlinger初始化的过程中,当SurfaceFlinger的init函数中,
// 调用HwComposer的setConfiguration函数时,由驱动测的Composer对象返回给系统一个设备添加的消息
// 从而触发默认显示设备的加载并获取默认DisplayDevice对象
if (const auto display = getDefaultDisplayDeviceLocked()) {
// 此后获取默认DeviceDisplay对象的显示区域,并设置给上述创建的BufferStateLayer对象
mRefreshRateOverlay->setViewport(display->getSize());
}
如上描述,因此
void RefreshRateOverlay::setViewport(ui::Size viewport) {
Rect frame(viewport.width >> 3, viewport.height >> 5);
frame.offsetBy(viewport.width >> 5, viewport.height >> 4);
// 设置BufferStateLayer对象的frame
mLayer->setFrame(frame);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
bool BufferStateLayer::setFrame(const Rect& frame) {
int x = frame.left;
int y = frame.top;
int w = frame.getWidth();
int h = frame.getHeight();
// ...... 判错设置代码,省略
if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y &&
mCurrentState.active.w == w && mCurrentState.active.h == h) {
return false;
}
//...... 判错设置代码,省略
mCurrentState.active.transform.set(x, y);
mCurrentState.active.w = w;
mCurrentState.active.h = h;
mCurrentState.sequence++;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
这边主要是更新mCurrentState的状态和有效区域等,不做具体讨论
调用change显示刷新率函数
在上述代码段中,最后一步,通过RefreshRateOverlay的changeRefreshRate函数来达到更新Layer的刷新率
// 从RefreshRateConfigs配置中获取到当前的刷新率
mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
// 获取对应fps对应的GraphicBuffer指针对象
auto buffer = mBufferCache[refreshRate.getFps()];
// 将上述获取到的GraphicBuffer指针对象设置给创建的图层BufferStateLayer
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence,
nsecs_t postTime, nsecs_t desiredPresentTime,
const client_cache_t& clientCacheId) {
// ...... 设置mCurrentState的参数,此处省略
// 声明当前显示的图层新增加一个(显示历史中)
mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime,
LayerHistory::LayerUpdateType::Buffer);
addFrameEvent(acquireFence, postTime, desiredPresentTime);
return true;
}
如上代码,当系统显示设备刷新的时候,我们创建的BufferStateLayer图层就被加入到显示图层中,并在显示设备中显现出来
更新上层的开发者模式中的显示刷新率菜单的开关
当第一步中的SurfaceFlinger创建完图层后,在开发者模式中需要将显示刷新率开关菜单更新一下,会调用updateShowRefreshRateSetting函数
@VisibleForTesting
void updateShowRefreshRateSetting() {
// magic communication with surface flinger.
try {
if (mSurfaceFlinger != null) {
final Parcel data = Parcel.obtain();
// 需要注意,此处不为NULL,也就是说这边需要返回值
final Parcel reply = Parcel.obtain();
// 同上面一样,此处为”android.os.ISurfaceComposer”
data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY);
// 这个值为2
data.writeInt(SETTING_VALUE_QUERY);
// Code和上面更新的code一致均为1034
mSurfaceFlinger.transact(SURFACE_FLINGER_CODE, data, reply, 0 /* flags */);
// 等到上述Binder通信完成,此处reply也就有值了,因此获取该值,并设置菜单的开关
final boolean enabled = reply.readBoolean();
((SwitchPreference) mPreference).setChecked(enabled);
reply.recycle();
data.recycle();
}
} catch (RemoteException ex) {
// intentional no-op
}
}
刚刚data中带的值是0或者1,此处设置为2,就导致调用函数不一致
case 1034: {
// 获取此前设定的数据信息,打开 or 关闭
switch (n = data.readInt32()) {
// ...... 0和1不会走到,因此此处省略
default: {
Mutex::Autolock lock(mStateLock);
// 哦哦哦,原来此处是直接设置RefreshRateOverlay指针对象是否创建成功
// 成功即表明传入的参数为1,而且创建了一个图层
// 为nullptr的时候表明,传入参数为0,或者流程出现问题,未能成功创建指针,因此返回失败
reply->writeBool(mRefreshRateOverlay != nullptr);
}
}
return NO_ERROR;
}
如上段代码及解析,此处直接更新了开发者模式中的显示刷新率菜单开关
总结
在打开或者关闭开发者模式中的显示刷新率菜单开关的时候,
首先,打开开关时会创建一个BufferStateLayer图层以及为图层添加对应的GraphicBuffer,同时将该图层加入到SurfaceFlinger需要显示的所有图层中,并且刷新显示设备
其次,通过和SurfaceFlinger之间的通信,保证确认SurfaceFlinger端创建和显示图层正常后,更新开发者模式中的显示刷新率菜单开关