• android windows管理(一)


    1、Android手机开机后,显示壁纸、桌面、状态栏
    是什么决定了它们的显示顺序和层级。壁纸在最下面,桌面和其它应用在中间、状态栏导航栏在最上面。
    2、window type

    3、壁纸window的添加过程

    3.1 frameworks\base\core\java\android\view\WindowManager.java
    public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
    
    • 1
    3.2 frameworks\base\services\java\com\android\server\SystemServer.java
        private static final String WALLPAPER_SERVICE_CLASS =
                "com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
    
    startOtherServices{
        ...
        if (context.getResources().getBoolean(R.bool.config_enableWallpaperService)) {
            t.traceBegin("StartWallpaperManagerService");
            //system server启动WallpaperManagerService
            mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
            t.traceEnd();
        } else {
            Slog.i(TAG, "Wallpaper service disabled by config");
        }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    3.3 frameworks\base\services\core\java\com\android\server\wallpaper\WallpaperManagerService.java
    //WallpaperManagerService构造方法
    public WallpaperManagerService(Context context) {
    	...
    	//LocalService
    	LocalServices.addService(WallpaperManagerInternal.class, new LocalService());
    	...
    }
    //LocalService内部类
        private final class LocalService extends WallpaperManagerInternal {
            @Override
            public void onDisplayReady(int displayId) {
                onDisplayReadyInternal(displayId);//onDisplayReady回调
            }
    
            @Override
            public void onScreenTurnedOn(int displayId) {
                notifyScreenTurnedOn(displayId);
            }
            @Override
            public void onScreenTurningOn(int displayId) {
                notifyScreenTurningOn(displayId);
            }
    
            @Override
            public void onKeyguardGoingAway() {
                notifyKeyguardGoingAway();
            }
        }
        //onDisplayReadyInternal
        private void onDisplayReadyInternal(int displayId) {
            synchronized (mLock) {
                if (mLastWallpaper == null) {
                    return;
                }
                if (supportsMultiDisplay(mLastWallpaper.connection)) {
                    final DisplayConnector connector =
                            mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId);
                    if (connector == null) return;
                    //wallpaper和display连接
                    connector.connectLocked(mLastWallpaper.connection, mLastWallpaper);
                    return;
                }
                // System wallpaper does not support multiple displays, attach this display to
                // the fallback wallpaper.
                if (mFallbackWallpaper != null) {
                    final DisplayConnector connector = mFallbackWallpaper
                            .connection.getDisplayConnectorOrCreate(displayId);
                    if (connector == null) return;
                    //wallpaper和display连接
                    connector.connectLocked(mFallbackWallpaper.connection, mFallbackWallpaper);
                } else {
                    Slog.w(TAG, "No wallpaper can be added to the new display");
                }
            }
        }
        //
            void connectLocked(WallpaperConnection connection, WallpaperData wallpaper) {
                if (connection.mService == null) {
                    Slog.w(TAG, "WallpaperService is not connected yet");
                    return;
                }
                TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
                t.traceBegin("WPMS.connectLocked-" + wallpaper.wallpaperComponent);
                if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
                //addWindowToken ,type传入TYPE_WALLPAPER
                mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId,
                        null /* options */);
                mWindowManagerInternal.setWallpaperShowWhenLocked(
                        mToken, (wallpaper.mWhich & FLAG_LOCK) != 0);
                final DisplayData wpdData =
                        mWallpaperDisplayHelper.getDisplayDataOrCreate(mDisplayId);
                try {
                	//connection.mService.attach
                    connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
                            wpdData.mWidth, wpdData.mHeight,
                            wpdData.mPadding, mDisplayId, wallpaper.mWhich);
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failed attaching wallpaper on display", e);
                    if (wallpaper != null && !wallpaper.wallpaperUpdating
                            && connection.getConnectedEngineSize() == 0) {
                        bindWallpaperComponentLocked(null /* componentName */, false /* force */,
                                false /* fromUser */, wallpaper, null /* reply */);
                    }
                }
                t.traceEnd();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    connection.mService.attach

    3.4 frameworks\base\core\java\android\service\wallpaper\WallpaperService.java
        class IWallpaperServiceWrapper extends IWallpaperService.Stub {
            private final WallpaperService mTarget;
    
            public IWallpaperServiceWrapper(WallpaperService context) {
                mTarget = context;
            }
    
            @Override
            public void attach(IWallpaperConnection conn, IBinder windowToken,
                    int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
                    int displayId, @SetWallpaperFlags int which) {
                Trace.beginSection("WPMS.ServiceWrapper.attach");
                IWallpaperEngineWrapper engineWrapper =
                        new IWallpaperEngineWrapper(mTarget, conn, windowToken, windowType,
                                isPreview, reqWidth, reqHeight, padding, displayId, which);
                synchronized (mActiveEngines) {
                    mActiveEngines.put(windowToken, engineWrapper);
                }
                if (DEBUG) {
                    Slog.v(TAG, "IWallpaperServiceWrapper Attaching window token " + windowToken);
                }
                Trace.endSection();
            }
    		//IWallpaperEngineWrapper构造方法
            IWallpaperEngineWrapper(WallpaperService service,
                    IWallpaperConnection conn, IBinder windowToken,
                    int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
                    int displayId, @SetWallpaperFlags int which) {
                mWallpaperManager = getSystemService(WallpaperManager.class);
                mCaller = new HandlerCaller(service, service.onProvideEngineLooper(), this, true);
                mConnection = conn;
                mWindowToken = windowToken;
                mWindowType = windowType;//window类型
                mIsPreview = isPreview;
                mReqWidth = reqWidth;
                mReqHeight = reqHeight;
                mDisplayPadding.set(padding);
                mDisplayId = displayId;
                mWhich = which;
    
                // Create a display context before onCreateEngine.
                mDisplayManager = getSystemService(DisplayManager.class);
                mDisplay = mDisplayManager.getDisplay(mDisplayId);
    
                if (mDisplay == null) {
                    // Ignore this engine.
                    throw new IllegalArgumentException("Cannot find display with id" + mDisplayId);
                }
                //发消息DO_ATTACH
                Message msg = mCaller.obtainMessage(DO_ATTACH);
                mCaller.sendMessage(msg);
            }
    	//handler接收DO_ATTACH消息
        case DO_ATTACH: {
            Trace.beginSection("WPMS.DO_ATTACH");
            doAttachEngine();
            Trace.endSection();
        return;
        }
    
            private void doAttachEngine() {
                Trace.beginSection("WPMS.onCreateEngine");
                Engine engine = onCreateEngine();
                Trace.endSection();
                mEngine = engine;
                Trace.beginSection("WPMS.mConnection.attachEngine-" + mDisplayId);
                try {
                    mConnection.attachEngine(this, mDisplayId);
                } catch (RemoteException e) {
                    engine.detach();
                    Log.w(TAG, "Wallpaper host disappeared", e);
                    return;
                } catch (IllegalStateException e) {
                    Log.w(TAG, "Connector instance already destroyed, "
                                    + "can't attach engine to non existing connector", e);
                    return;
                } finally {
                    Trace.endSection();
                }
                Trace.beginSection("WPMS.engine.attach");
                engine.attach(this);//
                Trace.endSection();
            }
            
            void attach(IWallpaperEngineWrapper wrapper) {
                if (DEBUG) Log.v(TAG, "attach: " + this + " wrapper=" + wrapper);
                if (mDestroyed) {
                    return;
                }
    
                mIWallpaperEngine = wrapper;
                mCaller = wrapper.mCaller;
                mConnection = wrapper.mConnection;
                mWindowToken = wrapper.mWindowToken;
                mSurfaceHolder.setSizeFromLayout();
                mInitializing = true;
                mSession = WindowManagerGlobal.getWindowSession();
    
                mWindow.setSession(mSession);
    
                mLayout.packageName = getPackageName();
                mIWallpaperEngine.mDisplayManager.registerDisplayListener(mDisplayListener,
                        mCaller.getHandler());
                mDisplay = mIWallpaperEngine.mDisplay;
                // Use window context of TYPE_WALLPAPER so client can access UI resources correctly.
                mDisplayContext = createDisplayContext(mDisplay)
                        .createWindowContext(TYPE_WALLPAPER, null /* options */);
                mDefaultDimAmount = mDisplayContext.getResources().getFloat(
                        com.android.internal.R.dimen.config_wallpaperDimAmount);
                mWallpaperDimAmount = mDefaultDimAmount;
                mPreviousWallpaperDimAmount = mWallpaperDimAmount;
                mDisplayState = mDisplay.getCommittedState();
                mMergedConfiguration.setOverrideConfiguration(
                        mDisplayContext.getResources().getConfiguration());
    
                if (DEBUG) Log.v(TAG, "onCreate(): " + this);
                Trace.beginSection("WPMS.Engine.onCreate");
                onCreate(mSurfaceHolder);
                Trace.endSection();
    
                mInitializing = false;
    
                mReportedVisible = false;
                Trace.beginSection("WPMS.Engine.updateSurface");
                updateSurface(false, false, false);//
                Trace.endSection();
            }
    //窗口参数
    final WindowManager.LayoutParams mLayout
    		= new WindowManager.LayoutParams();
    //更新壁纸
    void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
    ...
        if (!mCreated) {
            // Add window
            mLayout.alpha = 0.3f;
            mLayout.type = mIWallpaperEngine.mWindowType;
            mLayout.gravity = Gravity.START|Gravity.TOP;
            mLayout.setFitInsetsTypes(0 /* types */);
            mLayout.setTitle(WallpaperService.this.getClass().getName());
            mLayout.windowAnimations =
                    com.android.internal.R.style.Animation_Wallpaper;
            InputChannel inputChannel = new InputChannel();
    
            if (mSession.addToDisplay(mWindow, mLayout, View.VISIBLE,
                    mDisplay.getDisplayId(), WindowInsets.Type.defaultVisible(),
                    inputChannel, mInsetsState, mTempControls, new Rect(),
                    new float[1]) < 0) {
                Log.w(TAG, "Failed to add window while updating wallpaper surface.");
                return;
            }
            mSession.setShouldZoomOutWallpaper(mWindow, shouldZoomOutWallpaper());
            mCreated = true;
    
            mInputEventReceiver = new WallpaperInputEventReceiver(
                    inputChannel, Looper.myLooper());
        }
        
        mSurfaceHolder.mSurfaceLock.lock();
        mDrawingAllowed = true;
    
        if (!fixedSize) {
            mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding);
        } else {
            mLayout.surfaceInsets.set(0, 0, 0, 0);
        }
        final int relayoutResult = mSession.relayout(mWindow, mLayout, mWidth, mHeight,
                View.VISIBLE, 0, 0, 0, mWinFrames, mMergedConfiguration,
                mSurfaceControl, mInsetsState, mTempControls, mSyncSeqIdBundle);
        final Rect outMaxBounds = mMergedConfiguration.getMergedConfiguration()
                .windowConfiguration.getMaxBounds();
        if (!outMaxBounds.equals(maxBounds)) {
            Log.i(TAG, "Retry updateSurface because bounds changed from relayout: "
                    + maxBounds + " -> " + outMaxBounds);
            mSurfaceHolder.mSurfaceLock.unlock();
            mDrawingAllowed = false;
            mCaller.sendMessage(mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
                    redrawNeeded ? 1 : 0));
            return;
        }
    ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182

    mSession.addToDisplay

    3.5 frameworks\base\services\core\java\com\android\server\wm\Session.java
        public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
                int viewVisibility, int displayId, @InsetsType int requestedVisibleTypes,
                InputChannel outInputChannel, InsetsState outInsetsState,
                InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
                float[] outSizeCompatScale) {
            return mService.addWindow(this, window, attrs, viewVisibility, displayId,
                    UserHandle.getUserId(mUid), requestedVisibleTypes, outInputChannel, outInsetsState,
                    outActiveControls, outAttachedFrame, outSizeCompatScale);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

        public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
                int displayId, int requestUserId, @InsetsType int requestedVisibleTypes,
                InputChannel outInputChannel, InsetsState outInsetsState,
                InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
                float[] outSizeCompatScale) {
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    3.6 小结

    以上只是简单跟踪了一下wallpaper添加window的过程。
    整个过程中涉及到比较多的类和流程,比较复杂。

    对TYPE_WALLPAPER的window type进行了跟踪,没有对整个过程进行展开。
    可以看出window的添加过程。window的创建、窗口参数。

  • 相关阅读:
    ie浏览器兼容模式怎么设置?
    win10环境下PCL安装和配置回顾(一)
    SpringSecurity学习笔记(一)springSecurity的整体架构
    程序员转行短视频的故事(一)
    线程第一次启动和异常的注册(UEF的一个特性)
    Dubbo windows下Dubbo安装及相关配置
    【错误 :Segmentation fault 】以及gdb调试 core duumped文件
    《数据结构、算法与应用C++语言描述》-栈的应用-列车车厢重排问题
    最佳实践:路径路由匹配规则的设计与实现
    SiegedSec 黑客组织袭击北约网络系统
  • 原文地址:https://blog.csdn.net/a396604593/article/details/133091752