当前位置: 首页 > news >正文

鹰潭网站建设公司车墩做网站公司

鹰潭网站建设公司,车墩做网站公司,网站做引流,网站添加flash前言 在Android 12系统源码_屏幕设备#xff08;一#xff09;DisplayManagerService的启动这篇文章中我们具体分析了DisplayManagerService 的启动流程#xff0c;本篇文章我们将在这个的基础上具体来分析下设备屏幕适配器的创建过程。 一、注册屏幕适配器 系统是在Disp…前言 在Android 12系统源码_屏幕设备一DisplayManagerService的启动这篇文章中我们具体分析了DisplayManagerService 的启动流程本篇文章我们将在这个的基础上具体来分析下设备屏幕适配器的创建过程。 一、注册屏幕适配器 系统是在DisplayManagerService 的onStart方法中调用registerDefaultDisplayAdapters进行了默认屏幕适配器的注册在systemReady方法中调用registerAdditionalDisplayAdapters进行额外屏幕适配器的注册。 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;//注册其他屏幕适配器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屏幕适配器}}}}二、注册默认屏幕适配器 注册内置物理屏幕适配器和虚拟屏幕适配器调用的都是registerDisplayAdapterLocked方法。 public final class DisplayManagerService extends SystemService {//当前已经注册的屏幕适配器集合private final ArrayListDisplayAdapter mDisplayAdapters new ArrayListDisplayAdapter();//虚拟屏幕适配器private VirtualDisplayAdapter mVirtualDisplayAdapter;//注册默认的屏幕适配器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 registerDisplayAdapterLocked(DisplayAdapter adapter) {mDisplayAdapters.add(adapter);//将适配器对象添加到mDisplayAdapters集合中adapter.registerLocked();//进行适配器注册操作}}此方法先是创建内置物理屏幕适配器LocalDisplayAdapter对象实例然后获取虚拟屏幕适配器VirtualDisplayAdapter对象实例。进一步调用registerDisplayAdapterLocked方法将其添加到屏幕适配器集合mDisplayAdapters中然后还有调用每个适配器的registerLocked方法。 2.1 内置物理屏幕适配器 注册内置物理屏幕适配器先是创建LocalDisplayAdapter对象然后调用该对象的registerLocked方法。 frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java final class LocalDisplayAdapter extends DisplayAdapter {public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener) {this(syncRoot, context, handler, listener, new Injector());}VisibleForTestingLocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener, Injector injector) {super(syncRoot, context, handler, listener, TAG);//父类构造方法mInjector injector;mSurfaceControlProxy mInjector.getSurfaceControlProxy();}Overridepublic void registerLocked() {super.registerLocked();mInjector.setDisplayEventListenerLocked(getHandler().getLooper(),new LocalDisplayEventListener());// 从SurfaceControl中获取物理屏幕idfor (long physicalDisplayId : mSurfaceControlProxy.getPhysicalDisplayIds()) {//尝试连接物理屏幕tryConnectDisplayLocked(physicalDisplayId);}}private void tryConnectDisplayLocked(long physicalDisplayId) {// 根据id获取当前物理屏幕的令牌final IBinder displayToken mSurfaceControlProxy.getPhysicalDisplayToken(physicalDisplayId);if (displayToken ! null) {// 根据token获取当前物理屏幕的配置项SurfaceControl.StaticDisplayInfo staticInfo mSurfaceControlProxy.getStaticDisplayInfo(displayToken);if (staticInfo null) {Slog.w(TAG, No valid static info found for display device physicalDisplayId);return;}SurfaceControl.DynamicDisplayInfo dynamicInfo mSurfaceControlProxy.getDynamicDisplayInfo(displayToken);if (dynamicInfo null) {Slog.w(TAG, No valid dynamic info found for display device physicalDisplayId);return;}if (dynamicInfo.supportedDisplayModes null) {// There are no valid modes for this device, so we cant use itSlog.w(TAG, No valid modes found for display device physicalDisplayId);return;}if (dynamicInfo.activeDisplayModeId 0) {// There is no active mode, and for now we dont have the// policy to set one.Slog.w(TAG, No valid active mode found for display device physicalDisplayId);return;}if (dynamicInfo.activeColorMode 0) {// We failed to get the active color mode. We dont bail out here since on the next// configuration pass well go ahead and set it to whatever it was set to last (or// COLOR_MODE_NATIVE if this is the first configuration).Slog.w(TAG, No valid active color mode for display device physicalDisplayId);dynamicInfo.activeColorMode Display.COLOR_MODE_INVALID;}SurfaceControl.DesiredDisplayModeSpecs modeSpecs mSurfaceControlProxy.getDesiredDisplayModeSpecs(displayToken);// 根据id从mDevices数组中获取对应的LocalDisplayDeviceLocalDisplayDevice device mDevices.get(physicalDisplayId);if (device null) {//是否是默认屏幕final boolean isDefaultDisplay mDevices.size() 0;// 创建LocalDisplayDevicedevice new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,dynamicInfo, modeSpecs, isDefaultDisplay);mDevices.put(physicalDisplayId, device);//通知DMS更新DisplayDevice事件新增屏幕设备sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);} else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,modeSpecs)) {//通知DMS更新DisplayDevice事件屏幕设备属性发生变化sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);}} else {// The display is no longer available. Ignore the attempt to add it.// If it was connected but has already been disconnected, well get a// disconnect event that will remove it from mDevices.}} }2.1.1 构造方法 LocalDisplayAdapter的构造方法很简单主要属性的赋值都在其父类DisplayAdapter中。 final class LocalDisplayAdapter extends DisplayAdapter {public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener) {this(syncRoot, context, handler, listener, new Injector());}VisibleForTestingLocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener, Injector injector) {super(syncRoot, context, handler, listener, TAG);//父类构造方法mInjector injector;mSurfaceControlProxy mInjector.getSurfaceControlProxy();} }frameworks/base/services/core/java/com/android/server/display/DisplayAdapter.java abstract class DisplayAdapter {private final DisplayManagerService.SyncRoot mSyncRoot;private final Context mContext;private final Handler mHandler;private final Listener mListener;private final String mName;// Called with SyncRoot lock held.public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener, String name) {//DMS模块全局同步锁mSyncRoot syncRoot;mContext context;//android.display线程的HandlermHandler handler;//DislayApdater.Listener对象用于回调DMSmListener listener;mName name;}public void registerLocked() {} }2.1.2 创建物理屏对象 创建好物理屏幕适配器对象后会执行该对象的registerLocked()方法。 final class LocalDisplayAdapter extends DisplayAdapter {Overridepublic void registerLocked() {super.registerLocked();mInjector.setDisplayEventListenerLocked(getHandler().getLooper(), new LocalDisplayEventListener());// 从SurfaceControl中获取物理屏幕idfor (long physicalDisplayId : mSurfaceControlProxy.getPhysicalDisplayIds()) {//尝试连接物理屏幕tryConnectDisplayLocked(physicalDisplayId);}} }registerLocked方法首先通过SurfaceControl获得所有的物理显示屏幕id然后依次执行tryConnectDisplayLocked()方法根据id创建对应的物理显屏幕和DMS进行连接。 final class LocalDisplayAdapter extends DisplayAdapter {private final LongSparseArrayLocalDisplayDevice mDevices new LongSparseArray();private void tryConnectDisplayLocked(long physicalDisplayId) {// 根据id获取当前物理屏幕的令牌final IBinder displayToken mSurfaceControlProxy.getPhysicalDisplayToken(physicalDisplayId);if (displayToken ! null) {// 根据token获取当前物理屏幕的配置项SurfaceControl.StaticDisplayInfo staticInfo mSurfaceControlProxy.getStaticDisplayInfo(displayToken);if (staticInfo null) {Slog.w(TAG, No valid static info found for display device physicalDisplayId);return;}SurfaceControl.DynamicDisplayInfo dynamicInfo mSurfaceControlProxy.getDynamicDisplayInfo(displayToken);if (dynamicInfo null) {Slog.w(TAG, No valid dynamic info found for display device physicalDisplayId);return;}if (dynamicInfo.supportedDisplayModes null) {// There are no valid modes for this device, so we cant use itSlog.w(TAG, No valid modes found for display device physicalDisplayId);return;}if (dynamicInfo.activeDisplayModeId 0) {// There is no active mode, and for now we dont have the// policy to set one.Slog.w(TAG, No valid active mode found for display device physicalDisplayId);return;}if (dynamicInfo.activeColorMode 0) {// We failed to get the active color mode. We dont bail out here since on the next// configuration pass well go ahead and set it to whatever it was set to last (or// COLOR_MODE_NATIVE if this is the first configuration).Slog.w(TAG, No valid active color mode for display device physicalDisplayId);dynamicInfo.activeColorMode Display.COLOR_MODE_INVALID;}SurfaceControl.DesiredDisplayModeSpecs modeSpecs mSurfaceControlProxy.getDesiredDisplayModeSpecs(displayToken);// 根据id从mDevices数组中获取对应的LocalDisplayDeviceLocalDisplayDevice device mDevices.get(physicalDisplayId);if (device null) {//是否是默认屏幕final boolean isDefaultDisplay mDevices.size() 0;// 创建LocalDisplayDevicedevice new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,dynamicInfo, modeSpecs, isDefaultDisplay);mDevices.put(physicalDisplayId, device);//通知DMS更新DisplayDevice事件新增屏幕设备sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);} else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,modeSpecs)) {//通知DMS更新DisplayDevice事件屏幕设备属性发生变化sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);}} else {// The display is no longer available. Ignore the attempt to add it.// If it was connected but has already been disconnected, well get a// disconnect event that will remove it from mDevices.}} }这个方法先是从SurfaceControler中获取多个物理显示相关的配置属性然后根据物理设备id从mDevices数组中获取对应的LocalDisplayDevice如果不存在则会进行创建物理屏幕设备对象LocalDisplayDevice是LocalDisplayAdapter的静态内部类。 final class LocalDisplayAdapter extends DisplayAdapter {//物理屏幕设备对象private final class LocalDisplayDevice extends DisplayDevice {private final long mPhysicalDisplayId;private final SparseArrayDisplayModeRecord mSupportedModes new SparseArray();private final ArrayListInteger mSupportedColorModes new ArrayList();private final boolean mIsDefaultDisplay;//是否是默认屏幕private final BacklightAdapter mBacklightAdapter;//背光适配器private DisplayDeviceInfo mInfo;//屏幕设备信息private boolean mHavePendingChanges;private int mState Display.STATE_UNKNOWN;// This is only set in the runnable returned from requestDisplayStateLocked.private float mBrightnessState PowerManager.BRIGHTNESS_INVALID_FLOAT;private float mSdrBrightnessState PowerManager.BRIGHTNESS_INVALID_FLOAT;private int mDefaultModeId;private int mDefaultModeGroup;private int mActiveModeId;private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs new DisplayModeDirector.DesiredDisplayModeSpecs();private boolean mDisplayModeSpecsInvalid;private int mActiveColorMode;private Display.HdrCapabilities mHdrCapabilities;private boolean mAllmSupported;private boolean mGameContentTypeSupported;private boolean mAllmRequested;private boolean mGameContentTypeRequested;private boolean mSidekickActive;private SidekickInternal mSidekickInternal;private SurfaceControl.StaticDisplayInfo mStaticDisplayInfo;// The supported display modes according in SurfaceFlingerprivate SurfaceControl.DisplayMode[] mSfDisplayModes;// The active display mode in SurfaceFlingerprivate SurfaceControl.DisplayMode mActiveSfDisplayMode;private DisplayDeviceConfig mDisplayDeviceConfig;private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides new DisplayEventReceiver.FrameRateOverride[0];LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,SurfaceControl.StaticDisplayInfo staticDisplayInfo,SurfaceControl.DynamicDisplayInfo dynamicInfo,SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isDefaultDisplay) {// 设置mDisplayAdapter、mDisplayToken、mUniqueId三个属性super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX physicalDisplayId,getContext());//物理设备屏幕idmPhysicalDisplayId physicalDisplayId;// 是否是默认屏mIsDefaultDisplay isDefaultDisplay;// 更新物理屏配置物理屏配置、色彩模式、HDR模式updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);mSidekickInternal LocalServices.getService(SidekickInternal.class);//背光适配器mBacklightAdapter new BacklightAdapter(displayToken, isDefaultDisplay,mSurfaceControlProxy);mDisplayDeviceConfig null;}} }在创建物理屏幕设备对象或者更新物理屏幕设备对象属性后都会调用sendDisplayDeviceEventLocked方法通知DMS屏幕设备状态发生变化。 2.2、注册虚拟屏幕适配器 public class VirtualDisplayAdapter extends DisplayAdapter {public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener) {this(syncRoot, context, handler, listener,(String name, boolean secure) - SurfaceControl.createDisplay(name, secure));}VisibleForTestingVirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener,SurfaceControlDisplayFactory surfaceControlDisplayFactory) {super(syncRoot, context, handler, listener, TAG);mHandler handler;mSurfaceControlDisplayFactory surfaceControlDisplayFactory;}}VirtualDisplayAdapter的构造方法同样很简单主要属性的赋值同样是依赖于其父类DisplayAdapter值得一提的是该类没有重新父类的registerLocked方法意味着registerLocked方法是空实现。 三、 通知DMS屏幕设备状态发生变化 前面注册内置物理屏幕适配器的最后有提到sendDisplayDeviceEventLocked方法来看下该方法。 abstract class DisplayAdapter {private final Listener mListener;public interface Listener {void onDisplayDeviceEvent(DisplayDevice device, int event);void onTraversalRequested();}/*** 发送一个屏幕设备事件给屏幕设备适配器的监听者*/protected final void sendDisplayDeviceEventLocked(final DisplayDevice device, final int event) {mHandler.post(() - mListener.onDisplayDeviceEvent(device, event));} } 3.1 DisplayDeviceRepository阶段 DisplayDeviceRepository这个类实现了DisplayAdapter.Listener的回调方法。 frameworks/base/services/core/java/com/android/server/display/DisplayDeviceRepository.java class DisplayDeviceRepository implements DisplayAdapter.Listener {private final ListDisplayDevice mDisplayDevices new ArrayList();Overridepublic void onDisplayDeviceEvent(DisplayDevice device, int event) {switch (event) {case DISPLAY_DEVICE_EVENT_ADDED://新增屏幕设备handleDisplayDeviceAdded(device);break;case DISPLAY_DEVICE_EVENT_CHANGED://屏幕设备属性发生变化handleDisplayDeviceChanged(device);break;case DISPLAY_DEVICE_EVENT_REMOVED://屏幕设备被移除handleDisplayDeviceRemoved(device);break;}}private void handleDisplayDeviceAdded(DisplayDevice device) {synchronized (mSyncRoot) {DisplayDeviceInfo info device.getDisplayDeviceInfoLocked();if (mDisplayDevices.contains(device)) {Slog.w(TAG, Attempted to add already added display device: info);return;}Slog.i(TAG, Display device added: info);device.mDebugLastLoggedDeviceInfo info;mDisplayDevices.add(device);//调用sendEventLocked方法发送消息事件sendEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);}}private void handleDisplayDeviceChanged(DisplayDevice device) {synchronized (mSyncRoot) {final DisplayDeviceInfo info device.getDisplayDeviceInfoLocked();if (!mDisplayDevices.contains(device)) {Slog.w(TAG, Attempted to change non-existent display device: info);return;}int diff device.mDebugLastLoggedDeviceInfo.diff(info);if (diff DisplayDeviceInfo.DIFF_STATE) {Slog.i(TAG, Display device changed state: \ info.name \, Display.stateToString(info.state));} else if (diff ! 0) {Slog.i(TAG, Display device changed: info);}if ((diff DisplayDeviceInfo.DIFF_COLOR_MODE) ! 0) {try {mPersistentDataStore.setColorMode(device, info.colorMode);} finally {mPersistentDataStore.saveIfNeeded();}}device.mDebugLastLoggedDeviceInfo info;device.applyPendingDisplayDeviceInfoChangesLocked();//调用sendEventLocked方法发送消息事件sendEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);}}private void handleDisplayDeviceRemoved(DisplayDevice device) {synchronized (mSyncRoot) {DisplayDeviceInfo info device.getDisplayDeviceInfoLocked();if (!mDisplayDevices.remove(device)) {Slog.w(TAG, Attempted to remove non-existent display device: info);return;}Slog.i(TAG, Display device removed: info);device.mDebugLastLoggedDeviceInfo info;//调用sendEventLocked方法发送消息事件sendEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);}}}DisplayDeviceRepository的onDisplayDeviceEvent方法会根据收到的事件类型分别做处理 新增屏幕设备调用handleDisplayDeviceAdded方法屏幕设备属性发生变化调用handleDisplayDeviceChanged方法屏幕设备被移除调用handleDisplayDeviceRemoved方法。 以上三种场景最终都会进一步触发sendEventLocked方法。 class DisplayDeviceRepository implements DisplayAdapter.Listener {//屏幕设备状态发生变化事件监听者private final ListListener mListeners new ArrayList();private void sendEventLocked(DisplayDevice device, int event) {final int size mListeners.size();for (int i 0; i size; i) {//进一步触发回调对象的onDisplayDeviceEventLocked方法mListeners.get(i).onDisplayDeviceEventLocked(device, event);}}/*** Listens to {link DisplayDevice} events from {link DisplayDeviceRepository}.*/public interface Listener {void onDisplayDeviceEventLocked(DisplayDevice device, int event);// TODO: multi-display - Try to remove the need for requestTraversal...it feels like// a shoe-horned method for a shoe-horned feature.void onTraversalRequested();}; } LogicalDisplayMapper实现了DisplayDeviceRepository.Listener这个回调。 3.2 LogicalDisplayMapper阶段 LogicalDisplayMapper是系统逻辑屏幕设备对象的管理者。 frameworks/base/services/core/java/com/android/server/display/LogicalDisplayMapper.java class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {LogicalDisplayMapper(NonNull Context context, NonNull DisplayDeviceRepository repo,NonNull Listener listener, NonNull DisplayManagerService.SyncRoot syncRoot,NonNull Handler handler) {mSyncRoot syncRoot;mPowerManager context.getSystemService(PowerManager.class);mHandler new LogicalDisplayMapperHandler(handler.getLooper());mDisplayDeviceRepo repo;mListener listener;mSingleDisplayDemoMode SystemProperties.getBoolean(persist.demo.singledisplay, false);mSupportsConcurrentInternalDisplays context.getResources().getBoolean(com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);mDeviceStateOnWhichToWakeUp context.getResources().getInteger(com.android.internal.R.integer.config_deviceStateOnWhichToWakeUp);mDisplayDeviceRepo.addListener(this);mDeviceStateToLayoutMap new DeviceStateToLayoutMap();}Overridepublic void onDisplayDeviceEventLocked(DisplayDevice device, int event) {switch (event) {case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_ADDED://新增屏幕设备if (DEBUG) {Slog.d(TAG, Display device added: device.getDisplayDeviceInfoLocked());}handleDisplayDeviceAddedLocked(device);//break;case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_CHANGED://屏幕设备属性发生变化if (DEBUG) {Slog.d(TAG, Display device changed: device.getDisplayDeviceInfoLocked());}finishStateTransitionLocked(false /*force*/);updateLogicalDisplaysLocked();//更新逻辑屏幕设备的属性break;case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_REMOVED://移除屏幕设备if (DEBUG) {Slog.d(TAG, Display device removed: device.getDisplayDeviceInfoLocked());}updateLogicalDisplaysLocked();//更新逻辑屏幕设备的属性break;}} }LogicalDisplayMapper的onDisplayDeviceEventLocked方法也会根据收到的事件类型做分流处理 新增屏幕设备调用handleDisplayDeviceAddedLocked方法屏幕设备被移除或者屏幕设备属性发生变化调用updateLogicalDisplaysLocked方法 3.2.1 新增逻辑屏 class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {private void handleDisplayDeviceAddedLocked(DisplayDevice device) {// 获取DisplayDeviceInfo对象DisplayDeviceInfo deviceInfo device.getDisplayDeviceInfoLocked();// Internal Displays need to have additional initialization.// This initializes a default dynamic display layout for INTERNAL// devices, which is used as a fallback in case no static layout definitions// exist or cannot be loaded.if (deviceInfo.type Display.TYPE_INTERNAL) {initializeInternalDisplayDeviceLocked(device);}// 创建逻辑屏对象LogicalDisplay display createNewLogicalDisplayLocked(device, Layout.assignDisplayIdLocked(false /*isDefault*/));applyLayoutLocked();updateLogicalDisplaysLocked();}//创建逻辑屏幕private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice device, int displayId) {final int layerStack assignLayerStackLocked(displayId);final LogicalDisplay display new LogicalDisplay(displayId, layerStack, device);display.updateLocked(mDisplayDeviceRepo);mLogicalDisplays.put(displayId, display);setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED);return display;} }3.2.2 更新逻辑屏 class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {private void updateLogicalDisplaysLocked() {// Go through all the displays and figure out if they need to be updated.// Loops in reverse so that displays can be removed during the loop without affecting the// rest of the loop.for (int i mLogicalDisplays.size() - 1; i 0; i--) {final int displayId mLogicalDisplays.keyAt(i);LogicalDisplay display mLogicalDisplays.valueAt(i);mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo);display.updateLocked(mDisplayDeviceRepo);final DisplayInfo newDisplayInfo display.getDisplayInfoLocked();final int updateState mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);final boolean wasPreviouslyUpdated updateState ! UPDATE_STATE_NEW;// The display is no longer valid and needs to be removed.if (!display.isValidLocked()) {mUpdatedLogicalDisplays.delete(displayId);// Remove from groupfinal DisplayGroup displayGroup getDisplayGroupLocked(getDisplayGroupIdFromDisplayIdLocked(displayId));if (displayGroup ! null) {displayGroup.removeDisplayLocked(display);}if (wasPreviouslyUpdated) {// The display isnt actually removed from our internal data structures until// after the notification is sent; see {link #sendUpdatesForDisplaysLocked}.Slog.i(TAG, Removing display: displayId);mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_REMOVED);} else {// This display never left this class, safe to remove without notificationmLogicalDisplays.removeAt(i);}continue;// The display is new.} else if (!wasPreviouslyUpdated) {Slog.i(TAG, Adding new display: displayId : newDisplayInfo);assignDisplayGroupLocked(display);mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_ADDED);// Underlying displays device has changed to a different one.} else if (!TextUtils.equals(mTempDisplayInfo.uniqueId, newDisplayInfo.uniqueId)) {// FLAG_OWN_DISPLAY_GROUP could have changed, recalculate just in caseassignDisplayGroupLocked(display);mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_SWAPPED);// Something about the display device has changed.} else if (!mTempDisplayInfo.equals(newDisplayInfo)) {// FLAG_OWN_DISPLAY_GROUP could have changed, recalculate just in caseassignDisplayGroupLocked(display);mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);// The display is involved in a display layout transition} else if (updateState UPDATE_STATE_TRANSITION) {mLogicalDisplaysToUpdate.put(displayId,LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);// Display frame rate overrides changed.} else if (!display.getPendingFrameRateOverrideUids().isEmpty()) {mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);// Non-override display values changed.} else {// While application shouldnt know nor care about the non-overridden info, we// still need to let WindowManager know so it can update its own internal state for// things like display cutouts.display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo);if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) {mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);}}mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_UPDATED);}// Go through the groups and do the same thing. We do this after displays since group// information can change in the previous loop.// Loops in reverse so that groups can be removed during the loop without affecting the// rest of the loop.for (int i mDisplayGroups.size() - 1; i 0; i--) {final int groupId mDisplayGroups.keyAt(i);final DisplayGroup group mDisplayGroups.valueAt(i);final boolean wasPreviouslyUpdated mUpdatedDisplayGroups.indexOfKey(groupId) -1;final int changeCount group.getChangeCountLocked();if (group.isEmptyLocked()) {mUpdatedDisplayGroups.delete(groupId);if (wasPreviouslyUpdated) {mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_REMOVED);}continue;} else if (!wasPreviouslyUpdated) {mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_ADDED);} else if (mUpdatedDisplayGroups.get(groupId) ! changeCount) {mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_CHANGED);}mUpdatedDisplayGroups.put(groupId, changeCount);}// Send the display and display group updates in order by message type. This is important// to ensure that addition and removal notifications happen in the right order.sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_ADDED);sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED);sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED);sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_SWAPPED);sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_ADDED);sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_CHANGED);sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_REMOVED);mLogicalDisplaysToUpdate.clear();mDisplayGroupsToUpdate.clear();} }四、注册额外屏幕适配器 前面我们有提到DMS有在systemReady方法中调用registerAdditionalDisplayAdapters方法来进行额外屏幕适配器的注册。 public final class DisplayManagerService extends SystemService {//当前已经注册的屏幕适配器集合private final ArrayListDisplayAdapter mDisplayAdapters new ArrayListDisplayAdapter();//The Wifi display adapter, or null if not registered.private WifiDisplayAdapter mWifiDisplayAdapter;//注册额外的屏幕适配器对象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();//进行适配器注册操作}}4.1 模拟辅助设备适配器 注册模拟辅助设备适配器需要先创建OverlayDisplayAdapter对象然后调用该对象的registerLocked方法。 frameworks/base/services/core/java/com/android/server/display/OverlayDisplayAdapter.java final class OverlayDisplayAdapter extends DisplayAdapter {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() {//监听global数据库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();}});}}OverlayDisplayAdapter的registerLocked方法仅仅是对global数据库overlay_display_devices字段的变化进行了监听初次以及后续该字段变化的时候都会调用updateOverlayDisplayDevices方法关于overlay_display_devices这个字段的变化逻辑我们在Android 12系统源码_多屏幕二模拟辅助设备功能开关实现原理这篇文章有详细分析过。 final class OverlayDisplayAdapter extends DisplayAdapter {private final ArrayListOverlayDisplayHandle mOverlays new ArrayListOverlayDisplayHandle();//更新模拟辅助屏幕设备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集合ArrayListOverlayMode 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 ListOverlayMode 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,ListOverlayMode 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;}} }4.2 WIIFI屏幕设备适配器 注册WIFI设备适配器需要先创建WifiDisplayAdapter对象然后调用该对象的registerLocked方法。 frameworks/base/services/core/java/com/android/server/display/WifiDisplayAdapter.java final class WifiDisplayAdapter extends DisplayAdapter {private static final String ACTION_DISCONNECT android.server.display.wfd.DISCONNECT;private WifiDisplayController mDisplayController;public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener,PersistentDataStore persistentDataStore) {super(syncRoot, context, handler, listener, TAG);if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)) {throw new RuntimeException(WiFi display was requested, but there is no WiFi Direct feature);}mHandler new WifiDisplayHandler(handler.getLooper());mPersistentDataStore persistentDataStore;mSupportsProtectedBuffers context.getResources().getBoolean(com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);}Overridepublic void registerLocked() {super.registerLocked();updateRememberedDisplaysLocked();getHandler().post(new Runnable() {Overridepublic void run() {//创建WIFI屏幕设备控制器mDisplayController new WifiDisplayController(getContext(), getHandler(), mWifiDisplayListener);//注册广播接受者getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,new IntentFilter(ACTION_DISCONNECT), null, mHandler);}});}private final BroadcastReceiver mBroadcastReceiver new BroadcastReceiver() {Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals(ACTION_DISCONNECT)) {synchronized (getSyncRoot()) {//请求断开连接requestDisconnectLocked();}}}};public void requestDisconnectLocked() {getHandler().post(new Runnable() {Overridepublic void run() {if (mDisplayController ! null) {//请求断开连接mDisplayController.requestDisconnect();}}});} }WifiDisplayAdapter的registerLocked方法先是创建WifiDisplayController对象然后注册广播接受者监听android.server.display.wfd.DISCONNECT广播事件当收到该广播的时候执行requestDisconnectLocked方法该方法最终是调用WifiDisplayController的requestDisconnect方法。 五、总结
http://www.hkea.cn/news/14393092/

相关文章:

  • 网站建设在线推广百度搜索推广和信息流推广
  • 世界杯网站建设网站建设企业需要准备资料
  • 域名如何绑定网站电商运营基础知识
  • 建网站买什么主机惠州网络推广平台
  • 公司做网站需要提供的材料w3school网页制作
  • 做公司网站哪个好wordpress调用插件吗
  • 如何选择网站开发广告设计专业是干什么的
  • 广州做外贸网站建设企业网站开发技术期末试题
  • 网站建设实践考试试题wordpress多大vps
  • 怎么在360网站做词条咪呜瀑布流WordPress模板
  • 公司 宜宾网站建设网站开发完没人运营
  • 专业集团门户网站建设公司宁波建设网站
  • 用iis建立网站网站建设要那些东西
  • 做网站能挣多少钱中国江苏网
  • 自己造网站win2012服务器网站建设
  • 河东做网站公司高端食品wordpress
  • 做网站编写如何制作小视频
  • 爱站网做网站吗茂名网站建设方案外包
  • 惠州网站制作定制福建建设执业资格注册管理中心网站
  • wordpress怎么做相关相似文章链接seo培训教程视频
  • 传统行业网站建设seo优化是什么职位
  • 网站建站专家页面设计站在学员的角度
  • 网站推广的岗位要求wordpress hide
  • 建筑局网站代做外国空间网站
  • 百度推广效果怎么样公司网站关键词优化
  • 做视频的免费素材网站连锁店管理网站开发
  • 济南网站建设首推企优互联不错网店运营的基本流程
  • 怎么发布自己的网站湖州网站建设湖州网站建设
  • 出入青岛最新通知今天seo优化培训学校
  • 宁波网站建设与设计制作wordpress自定义模块