Android 12系统源码_多屏幕(三)模拟辅助设备功能实现原理

2024-08-22 07:04

本文主要是介绍Android 12系统源码_多屏幕(三)模拟辅助设备功能实现原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

上一篇我们我们具体分析了Android系统开发者选项页面,模拟辅助设备功能开关的具体实现原理,当我们选择以下条目:

    <!-- 模拟辅助设备的条目标题 --><string-array name="overlay_display_devices_entries"><item msgid="4497393944195787240">"无"</item><item msgid="8461943978957133391">"480p"</item><item msgid="6923083594932909205">"480p(安全)"</item><item msgid="1226941831391497335">"720p"</item><item msgid="7051983425968643928">"720p(安全)"</item><item msgid="7765795608738980305">"1080p"</item><item msgid="8084293856795803592">"1080p(安全)"</item><item msgid="938784192903353277">"4K"</item><item msgid="8612549335720461635">"4K(安全)"</item><item msgid="7322156123728520872">"4K(画质提升)"</item><item msgid="7735692090314849188">"4K(画质提升、安全)"</item><item msgid="7346816300608639624">"720p,1080p(双屏)"</item></string-array>

发现该开关的本质就是修改global数据库的overlay_display_devices字段的内容为以下条目属性值:

    <!-- 模拟辅助设备的条目属性值 --><string-array name="overlay_display_devices_values" translatable="false" ><item></item><item>720x480/142</item><item>720x480/142,secure</item><item>1280x720/213</item><item>1280x720/213,secure</item><item>1920x1080/320</item><item>1920x1080/320,secure</item><item>3840x2160/320</item><item>3840x2160/320,secure</item><item>1920x1080/320|3840x2160/640</item><item>1920x1080/320|3840x2160/640,secure</item><item>1280x720/213;1920x1080/320</item></string-array>

然后DisplayManagerService模块的OverlayDisplayAdapter会收到该字段变化的回调并做出响应,本篇文章我们具体来分析一下OverlayDisplayAdapter的响应过程。

一、DMS注册屏幕设配器

系统启动的时候会在SystemServer中启动DisplayManagerService,DisplayManagerService会依次注册内置物理屏幕适配器LocalDisplayAdapter、虚拟屏幕适配器VirtualDisplayAdapter 、模拟辅助屏幕适配器OverlayDisplayAdapter、Wifi屏幕适配器WifiDisplayAdapter。

frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

public final class DisplayManagerService extends SystemService {private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;//注册默认屏幕适配器private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;//注册其他屏幕适配器//当前已经注册的屏幕适配器集合private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();//虚拟屏幕适配器private VirtualDisplayAdapter mVirtualDisplayAdapter;//WIFI屏幕适配器private WifiDisplayAdapter mWifiDisplayAdapter;@Overridepublic void onStart() {...代码省略...// 在android.display线程中创建默认DisplayAdapter,并进行注册mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);...代码省略...}public void systemReady(boolean safeMode, boolean onlyCore) {...代码省略...  //注册除了物理屏幕适配器、虚拟屏幕适配器以外的其他屏幕适配器mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);...代码省略...}private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS://注册默认的屏幕适配器registerDefaultDisplayAdapters();break;case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS://注册额外的屏幕设备适配器registerAdditionalDisplayAdapters();break;...代码省略...    }}}//注册默认的屏幕适配器private void registerDefaultDisplayAdapters() {synchronized (mSyncRoot) {//注册内置物理屏幕适配器registerDisplayAdapterLocked(new LocalDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo));//注册虚拟屏幕适配器mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,mHandler, mDisplayDeviceRepo);if (mVirtualDisplayAdapter != null) {registerDisplayAdapterLocked(mVirtualDisplayAdapter);}}}//注册额外的屏幕适配器对象private void registerAdditionalDisplayAdapters() {synchronized (mSyncRoot) {if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {registerOverlayDisplayAdapterLocked();//注册模拟辅助设备屏幕适配器registerWifiDisplayAdapterLocked();//注册WIFI屏幕适配器}}}//注册模拟辅助屏幕设备适配器private void registerOverlayDisplayAdapterLocked() {registerDisplayAdapterLocked(new OverlayDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler));}//注册Wifi屏幕设备适配器private void registerWifiDisplayAdapterLocked() {if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableWifiDisplay)|| SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {mWifiDisplayAdapter = new WifiDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,mPersistentDataStore);registerDisplayAdapterLocked(mWifiDisplayAdapter);}}private void registerDisplayAdapterLocked(DisplayAdapter adapter) {mDisplayAdapters.add(adapter);//将适配器对象添加到mDisplayAdapters集合中adapter.registerLocked();//进行适配器注册操作}}

对以上代码做个简单总结:

  • onStart阶段,调用registerDefaultDisplayAdapters方法,注册内置物理屏幕适配器和虚拟屏幕适配器。
  • systemReady阶段,调用registerAdditionalDisplayAdapters方法,注册模拟辅助设备屏幕适配器和WIFI屏幕适配器。
  • 不管是注册哪种适配器,都是先创建适配器对象,将该对象添加到适配器集合mDisplayAdapters里面,并且会调用每个适配器对象的registerLocked方法。

二、OverlayDisplayAdapter的监听模拟辅助设备功能开关

2.1 监听overlay_display_devices字段属性值的变化

OverlayDisplayAdapter的registerLocked方法如下所示。

frameworks/base/services/core/java/com/android/server/display/OverlayDisplayAdapter.java

final class OverlayDisplayAdapter extends DisplayAdapter {private final Handler mUiHandler;//处于UI线程的Handler// Called with SyncRoot lock held.public OverlayDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener, Handler uiHandler) {super(syncRoot, context, handler, listener, TAG);mUiHandler = uiHandler;}@Overridepublic void registerLocked() {super.registerLocked();getHandler().post(new Runnable() {@Overridepublic void run() {//注册监听overlay_display_devices字段的内容变化getContext().getContentResolver().registerContentObserver(Settings.Global.getUriFor(Settings.Global.OVERLAY_DISPLAY_DEVICES),true, new ContentObserver(getHandler()) {@Overridepublic void onChange(boolean selfChange) {	//触发回调updateOverlayDisplayDevices();}});updateOverlayDisplayDevices();}});}private void updateOverlayDisplayDevices() {synchronized (getSyncRoot()) {//继续调用updateOverlayDisplayDevicesLocked方法updateOverlayDisplayDevicesLocked();}}}

该方法只是在当前线程中注册监听overlay_display_devices字段的内容变化,初次以及后续该字段变化的时候都会调用updateOverlayDisplayDevices方法。

2.2 解析overlay_display_devices的属性值

final class OverlayDisplayAdapter extends DisplayAdapter {private final ArrayList<OverlayDisplayHandle> mOverlays = new ArrayList<OverlayDisplayHandle>();//更新模拟辅助屏幕设备private void updateOverlayDisplayDevices() {synchronized (getSyncRoot()) {updateOverlayDisplayDevicesLocked();}}private void updateOverlayDisplayDevicesLocked() {//获取当前overlay_display_devices的属性值,例如【1920x1080/320】String value = Settings.Global.getString(getContext().getContentResolver(),Settings.Global.OVERLAY_DISPLAY_DEVICES);//如果为空直接返回if (value == null) {value = "";}//如果没有发生变化直接返回if (value.equals(mCurrentOverlaySetting)) {return;}mCurrentOverlaySetting = value;//清除目前已经存在的所有模拟辅助显示设备if (!mOverlays.isEmpty()) {Slog.i(TAG, "Dismissing all overlay display devices.");for (OverlayDisplayHandle overlay : mOverlays) {overlay.dismissLocked();}mOverlays.clear();}//对overlay_display_devices字段的内容进行解析int count = 0;for (String part : value.split(DISPLAY_SPLITTER)) {Matcher displayMatcher = DISPLAY_PATTERN.matcher(part);if (displayMatcher.matches()) {if (count >= 4) {Slog.w(TAG, "Too many overlay display devices specified: " + value);break;}String modeString = displayMatcher.group(1);String flagString = displayMatcher.group(2);//将字符串转化为OverlayMode集合ArrayList<OverlayMode> modes = new ArrayList<>();for (String mode : modeString.split(MODE_SPLITTER)) {Matcher modeMatcher = MODE_PATTERN.matcher(mode);if (modeMatcher.matches()) {try {int width = Integer.parseInt(modeMatcher.group(1), 10);int height = Integer.parseInt(modeMatcher.group(2), 10);int densityDpi = Integer.parseInt(modeMatcher.group(3), 10);if (width >= MIN_WIDTH && width <= MAX_WIDTH&& height >= MIN_HEIGHT && height <= MAX_HEIGHT&& densityDpi >= DisplayMetrics.DENSITY_LOW&& densityDpi <= DisplayMetrics.DENSITY_XXXHIGH) {modes.add(new OverlayMode(width, height, densityDpi));continue;} else {Slog.w(TAG, "Ignoring out-of-range overlay display mode: " + mode);}} catch (NumberFormatException ex) {}} else if (mode.isEmpty()) {continue;}}//解析OverlayMode集合if (!modes.isEmpty()) {int number = ++count;String name = getContext().getResources().getString(com.android.internal.R.string.display_manager_overlay_display_name,number);int gravity = chooseOverlayGravity(number);OverlayFlags flags = OverlayFlags.parseFlags(flagString);Slog.i(TAG, "Showing overlay display device #" + number+ ": name=" + name + ", modes=" + Arrays.toString(modes.toArray())+ ", flags=" + flags);//为其创建OverlayDisplayHandle对象,并将该对象添加到mOverlays集合中mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, flags, number));continue;}}Slog.w(TAG, "Malformed overlay display devices setting: " + value);}}private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener {private static final int DEFAULT_MODE_INDEX = 0;private final String mName;private final List<OverlayMode> mModes;private final int mGravity;private final OverlayFlags mFlags;private final int mNumber;private OverlayDisplayWindow mWindow;private OverlayDisplayDevice mDevice;private int mActiveMode;OverlayDisplayHandle(String name,List<OverlayMode> modes,int gravity,OverlayFlags flags,int number) {mName = name;mModes = modes;mGravity = gravity;mFlags = flags;mNumber = number;mActiveMode = 0;showLocked();//显示模拟辅助屏幕设备}private void showLocked() {//保证mShowRunnable是运行在UI线程中的mUiHandler.post(mShowRunnable);}public void dismissLocked() {//移除显示模拟辅助屏幕设备的RunnablemUiHandler.removeCallbacks(mShowRunnable);//执行销毁模拟辅助屏幕设备的RunnablemUiHandler.post(mDismissRunnable);}private void onActiveModeChangedLocked(int index) {mUiHandler.removeCallbacks(mResizeRunnable);mActiveMode = index;if (mWindow != null) {mUiHandler.post(mResizeRunnable);}}// Called on the UI thread.@Overridepublic void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate,long presentationDeadlineNanos, int state) {synchronized (getSyncRoot()) {IBinder displayToken = SurfaceControl.createDisplay(mName, mFlags.mSecure);mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode,DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos,mFlags, state, surfaceTexture, mNumber) {@Overridepublic void onModeChangedLocked(int index) {onActiveModeChangedLocked(index);}};sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);}}// Called on the UI thread.@Overridepublic void onWindowDestroyed() {synchronized (getSyncRoot()) {if (mDevice != null) {mDevice.destroyLocked();sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);}}}// Called on the UI thread.@Overridepublic void onStateChanged(int state) {synchronized (getSyncRoot()) {if (mDevice != null) {mDevice.setStateLocked(state);sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED);}}}public void dumpLocked(PrintWriter pw) {pw.println("  " + mName + ":");pw.println("    mModes=" + Arrays.toString(mModes.toArray()));pw.println("    mActiveMode=" + mActiveMode);pw.println("    mGravity=" + mGravity);pw.println("    mFlags=" + mFlags);pw.println("    mNumber=" + mNumber);// Try to dump the window state.if (mWindow != null) {final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");ipw.increaseIndent();DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, "", 200);}}// Runs on the UI thread. 显示窗口private final Runnable mShowRunnable = new Runnable() {@Overridepublic void run() {OverlayMode mode = mModes.get(mActiveMode);//创建模拟辅助设备屏幕对应的窗口OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(),mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity,mFlags.mSecure, OverlayDisplayHandle.this);//显示窗口window.show();synchronized (getSyncRoot()) {mWindow = window;}}};// Runs on the UI thread. 关闭窗口private final Runnable mDismissRunnable = new Runnable() {@Overridepublic void run() {OverlayDisplayWindow window;synchronized (getSyncRoot()) {window = mWindow;mWindow = null;}if (window != null) {window.dismiss();}}};// Runs on the UI thread. 缩放窗口private final Runnable mResizeRunnable = new Runnable() {@Overridepublic void run() {OverlayMode mode;OverlayDisplayWindow window;synchronized (getSyncRoot()) {if (mWindow == null) {return;}mode = mModes.get(mActiveMode);window = mWindow;}window.resize(mode.mWidth, mode.mHeight, mode.mDensityDpi);}};}private static final class OverlayMode {final int mWidth;//宽度final int mHeight;//高度final int mDensityDpi;//像素密度OverlayMode(int width, int height, int densityDpi) {mWidth = width;mHeight = height;mDensityDpi = densityDpi;}}
}

此方法先获取当前global数据库中overlay_display_devices的属性值,对该属性值内容进行字符串解析,将该字符串转化为OverlayMode对象集合,然后以该集合中的每个对象作为参数创建OverlayDisplayHandle对象,并将其添加到mOverlays集合中;OverlayDisplayHandle的构造方法中会调用showLocked方法,该方法会在UI线程中创建模拟辅助设备屏幕对应的OverlayDisplayWindow窗口。

三、模拟辅助显示设备窗口

通过第二节的分析可知,模拟辅助设备屏幕适配器OverlayDisplayAdapter会解析global数据库overlay_display_devices字段的属性内容,然后在默认屏幕中创建对应的OverlayDisplayWindow窗口。

3.1 构造方法

OverlayDisplayWindow的构造方法如下所示。

frameworks/base/services/core/java/com/android/server/display/OverlayDisplayWindow.java

final class OverlayDisplayWindow implements DumpUtils.Dump {public interface Listener {public void onWindowCreated(SurfaceTexture surfaceTexture,float refreshRate, long presentationDeadlineNanos, int state);public void onWindowDestroyed();public void onStateChanged(int state);}private final Context mContext;private final String mName;//窗口名称private int mWidth;//宽度private int mHeight;//高度private int mDensityDpi;//像素密度private final int mGravity;//窗口显示位置private final boolean mSecure;//是否是安全模式private final Listener mListener;//窗口事件回调private String mTitle;//窗口标题public OverlayDisplayWindow(Context context, String name,int width, int height, int densityDpi, int gravity, boolean secure,Listener listener) {ThreadedRenderer.disableVsync();mContext = context;mName = name;mGravity = gravity;mSecure = secure;mListener = listener;mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);//当前系统的默认屏幕设备mDefaultDisplay = mContext.getDisplay();//更新默认屏幕设备信息updateDefaultDisplayInfo();//设置窗口的宽高像素密度resize(width, height, densityDpi, false /* doLayout */);//创建窗口createWindow();}private void resize(int width, int height, int densityDpi, boolean doLayout) {mWidth = width;mHeight = height;mDensityDpi = densityDpi;//窗口标题mTitle = mContext.getResources().getString(com.android.internal.R.string.display_manager_overlay_display_title,mName, mWidth, mHeight, mDensityDpi);if (mSecure) {mTitle += mContext.getResources().getString(com.android.internal.R.string.display_manager_overlay_display_secure_suffix);}if (doLayout) {relayout();}}public void relayout() {//如果窗口可见,更新窗口参数if (mWindowVisible) {updateWindowParams();mWindowManager.updateViewLayout(mWindowContent, mWindowParams);}}private void createWindow() {...代码省略...}}

构造方法主要是对窗口属性进行赋值操作,最后会调用createWindow来创建具体的窗口视图。

3.2 加载窗口视图内容

来看下OverlayDisplayWindow的createWindow方法。

final class OverlayDisplayWindow implements DumpUtils.Dump {private final boolean DISABLE_MOVE_AND_RESIZE = false;//禁止移动缩放private View mWindowContent;//窗口视图private WindowManager.LayoutParams mWindowParams;//窗口参数private TextureView mTextureView;//模拟辅助显示设备的屏幕内容private TextView mTitleTextView;//窗口标题private GestureDetector mGestureDetector;private ScaleGestureDetector mScaleGestureDetector;private boolean mWindowVisible;//窗口是否可见private int mWindowX;//窗口左上角X坐标private int mWindowY;//窗口左上角Y坐标private float mWindowScale;//窗口缩放比例private void createWindow() {LayoutInflater inflater = LayoutInflater.from(mContext);//窗口对应的UI视图mWindowContent = inflater.inflate(com.android.internal.R.layout.overlay_display_window, null);mWindowContent.setOnTouchListener(mOnTouchListener);mTextureView = (TextureView)mWindowContent.findViewById(com.android.internal.R.id.overlay_display_window_texture);mTextureView.setPivotX(0);mTextureView.setPivotY(0);mTextureView.getLayoutParams().width = mWidth;mTextureView.getLayoutParams().height = mHeight;mTextureView.setOpaque(false);mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);mTitleTextView = (TextView)mWindowContent.findViewById(com.android.internal.R.id.overlay_display_window_title);mTitleTextView.setText(mTitle);//窗口类型为TYPE_DISPLAY_OVERLAYmWindowParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY);//窗口默认属性mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;//安全模式if (mSecure) {mWindowParams.flags |= WindowManager.LayoutParams.FLAG_SECURE;}//禁止移动和缩放if (DISABLE_MOVE_AND_RESIZE) {mWindowParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;}mWindowParams.privateFlags |=WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;//窗口透明度mWindowParams.alpha = WINDOW_ALPHA;//窗口所在位置,默认为左上角mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;//窗口标题mWindowParams.setTitle(mTitle);mGestureDetector = new GestureDetector(mContext, mOnGestureListener);mScaleGestureDetector = new ScaleGestureDetector(mContext, mOnScaleGestureListener);// Set the initial position and scale.// The position and scale will be clamped when the display is first shown.mWindowX = (mGravity & Gravity.LEFT) == Gravity.LEFT ?0 : mDefaultDisplayInfo.logicalWidth;mWindowY = (mGravity & Gravity.TOP) == Gravity.TOP ?0 : mDefaultDisplayInfo.logicalHeight;mWindowScale = INITIAL_SCALE;}}

frameworks/base/core/res/res/layout/overlay_display_window.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000000"><TextureView android:id="@+id/overlay_display_window_texture"android:layout_width="0px"android:layout_height="0px" /><TextView android:id="@+id/overlay_display_window_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="top|center_horizontal" />
</FrameLayout>

createWindow方法先是加载overlay_display_window布局文件,该布局只有两个控件,负责模拟辅助显示设备屏幕视图内容渲染的TextureView控件和标识窗口标题的TextView控件,随后会在代码中对这两个控件进行初始化并设置窗口显示需要的相关参数。

3.3 显示和隐藏窗口

可以通过调用OverlayDisplayWindow的show和dismiss方法控制OverlayDisplayWindow的显示和隐藏。

final class OverlayDisplayWindow implements DumpUtils.Dump {private final DisplayManager mDisplayManager;private final WindowManager mWindowManager;//显示窗口public void show() {if (!mWindowVisible) {mDisplayManager.registerDisplayListener(mDisplayListener, null);if (!updateDefaultDisplayInfo()) {mDisplayManager.unregisterDisplayListener(mDisplayListener);return;}clearLiveState();updateWindowParams();//将窗口视图添加到WindowManagerService中mWindowManager.addView(mWindowContent, mWindowParams);mWindowVisible = true;}}//隐藏窗口public void dismiss() {if (mWindowVisible) {mDisplayManager.unregisterDisplayListener(mDisplayListener);//将窗口视图从WindowManagerService中移除mWindowManager.removeView(mWindowContent);mWindowVisible = false;}}
}

四、模拟屏幕内容显示同步

每个模拟辅助显示设备的屏幕信息都是通过TextureView控件实时显示到OverlayDisplayWindow窗口上的。

4.1 OverlayDisplayWindow回调阶段

final class OverlayDisplayWindow implements DumpUtils.Dump {public interface Listener {public void onWindowCreated(SurfaceTexture surfaceTexture,float refreshRate, long presentationDeadlineNanos, int state);public void onWindowDestroyed();public void onStateChanged(int state);}private final Listener mListener;private TextureView mTextureView;//模拟辅助显示设备的屏幕内容private void createWindow() {LayoutInflater inflater = LayoutInflater.from(mContext);mWindowContent = inflater.inflate(com.android.internal.R.layout.overlay_display_window, null);mWindowContent.setOnTouchListener(mOnTouchListener);mTextureView = (TextureView)mWindowContent.findViewById(com.android.internal.R.id.overlay_display_window_texture);mTextureView.setPivotX(0);mTextureView.setPivotY(0);mTextureView.getLayoutParams().width = mWidth;mTextureView.getLayoutParams().height = mHeight;mTextureView.setOpaque(false);mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);//设置回调...代码省略...}private final SurfaceTextureListener mSurfaceTextureListener =new SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {//触发Listener的onWindowCreated方法mListener.onWindowCreated(surfaceTexture,mDefaultDisplayInfo.getRefreshRate(),mDefaultDisplayInfo.presentationDeadlineNanos, mDefaultDisplayInfo.state);}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {mListener.onWindowDestroyed();return true;}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,int width, int height) {}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}};
}

结合以上代码可以发现OverlayDisplayWindow窗口被添加到WindowManagerService之后,会触发SurfaceTextureListener的onSurfaceTextureAvailable方法,该方法会进一步回调Listener的onWindowCreated方法,OverlayDisplayAdapter$OverlayDisplayHandle类实现了这个回调接口。

4.2 OverlayDisplayAdapter$OverlayDisplayHandle回调阶段

final class OverlayDisplayAdapter extends DisplayAdapter {private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener {// Called on the UI thread.@Overridepublic void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate,long presentationDeadlineNanos, int state) {synchronized (getSyncRoot()) {//通过SurfaceControl创建一个屏幕设备,并返回该屏幕对应的令牌IBinder displayToken = SurfaceControl.(mName, mFlags.mSecure);//创建模拟辅助屏幕设备对象mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode,DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos,mFlags, state, surfaceTexture, mNumber) {@Overridepublic void onModeChangedLocked(int index) {onActiveModeChangedLocked(index);}};//通知DMS更新DisplayDevice事件,新增屏幕设备sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);}}// Called on the UI thread.@Overridepublic void onWindowDestroyed() {synchronized (getSyncRoot()) {if (mDevice != null) {mDevice.destroyLocked();//通知DMS更新DisplayDevice事件,屏幕设备被移除sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);}}}// Called on the UI thread.@Overridepublic void onStateChanged(int state) {synchronized (getSyncRoot()) {if (mDevice != null) {mDevice.setStateLocked(state);//通知DMS更新DisplayDevice事件,屏幕设备状态发生变化sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED);}}}}
}
  • onWindowCreated方法被回调的时候,会调用SurfaceControl的createDisplay方法创建屏幕设备,然后会创建OverlayDisplayDevice对象实例,并通知DMS更新DisplayDevice事件,新增屏幕设备。
  • onWindowDestroyed方法被回调的时候,会调用OverlayDisplayDevice对象实例的destroyLocked方法,并通知DMS更新DisplayDevice事件,屏幕设备被移除
  • onStateChanged方法被回调的时候,会调用OverlayDisplayDevice对象实例的setStateLocked方法,并通知DMS更新DisplayDevice事件,屏幕设备状态发生变化。

4.3 OverlayDisplayDevice对象

final class OverlayDisplayAdapter extends DisplayAdapter {private abstract class OverlayDisplayDevice extends DisplayDevice {private final String mName;private final float mRefreshRate;private final long mDisplayPresentationDeadlineNanos;private final OverlayFlags mFlags;private final List<OverlayMode> mRawModes;private final Display.Mode[] mModes;private final int mDefaultMode;private int mState;private SurfaceTexture mSurfaceTexture;//模拟辅助显示弹窗对应的渲染视图private Surface mSurface;//屏幕视图private DisplayDeviceInfo mInfo;private int mActiveMode;OverlayDisplayDevice(IBinder displayToken, String name,List<OverlayMode> modes, int activeMode, int defaultMode,float refreshRate, long presentationDeadlineNanos,OverlayFlags flags, int state, SurfaceTexture surfaceTexture, int number) {super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number,getContext());mName = name;mRefreshRate = refreshRate;mDisplayPresentationDeadlineNanos = presentationDeadlineNanos;mFlags = flags;mState = state;mSurfaceTexture = surfaceTexture;mRawModes = modes;mModes = new Display.Mode[modes.size()];for (int i = 0; i < modes.size(); i++) {OverlayMode mode = modes.get(i);mModes[i] = createMode(mode.mWidth, mode.mHeight, refreshRate);}mActiveMode = activeMode;mDefaultMode = defaultMode;}public void destroyLocked() {mSurfaceTexture = null;if (mSurface != null) {mSurface.release();mSurface = null;}SurfaceControl.destroyDisplay(getDisplayTokenLocked());}@Overridepublic boolean hasStableUniqueId() {return false;}@Overridepublic void performTraversalLocked(SurfaceControl.Transaction t) {//实时更新屏幕视图内容到模拟辅助弹窗的UI上if (mSurfaceTexture != null) {if (mSurface == null) {mSurface = new Surface(mSurfaceTexture);}setSurfaceLocked(t, mSurface);}}public void setStateLocked(int state) {mState = state;mInfo = null;}@Overridepublic DisplayDeviceInfo getDisplayDeviceInfoLocked() {if (mInfo == null) {Display.Mode mode = mModes[mActiveMode];OverlayMode rawMode = mRawModes.get(mActiveMode);mInfo = new DisplayDeviceInfo();mInfo.name = mName;mInfo.uniqueId = getUniqueId();mInfo.width = mode.getPhysicalWidth();mInfo.height = mode.getPhysicalHeight();mInfo.modeId = mode.getModeId();mInfo.defaultModeId = mModes[0].getModeId();mInfo.supportedModes = mModes;mInfo.densityDpi = rawMode.mDensityDpi;mInfo.xDpi = rawMode.mDensityDpi;mInfo.yDpi = rawMode.mDensityDpi;mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos +1000000000L / (int) mRefreshRate;   // display's deadline + 1 framemInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION;if (mFlags.mSecure) {mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;}if (mFlags.mOwnContentOnly) {mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;}if (mFlags.mShouldShowSystemDecorations) {mInfo.flags |= DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;}mInfo.type = Display.TYPE_OVERLAY;mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL;mInfo.state = mState;// The display is trusted since it is created by system.mInfo.flags |= FLAG_TRUSTED;}return mInfo;}@Overridepublic void setDesiredDisplayModeSpecsLocked(DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {final int id = displayModeSpecs.baseModeId;int index = -1;if (id == 0) {// Use the default.index = 0;} else {for (int i = 0; i < mModes.length; i++) {if (mModes[i].getModeId() == id) {index = i;break;}}}if (index == -1) {Slog.w(TAG, "Unable to locate mode " + id + ", reverting to default.");index = mDefaultMode;}if (mActiveMode == index) {return;}mActiveMode = index;mInfo = null;sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);onModeChangedLocked(index);}/*** Called when the device switched to a new mode.** @param index index of the mode in the list of modes*/public abstract void onModeChangedLocked(int index);}
}

这篇关于Android 12系统源码_多屏幕(三)模拟辅助设备功能实现原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095571

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Spring Security自定义身份认证的实现方法

《SpringSecurity自定义身份认证的实现方法》:本文主要介绍SpringSecurity自定义身份认证的实现方法,下面对SpringSecurity的这三种自定义身份认证进行详细讲解,... 目录1.内存身份认证(1)创建配置类(2)验证内存身份认证2.JDBC身份认证(1)数据准备 (2)配置依