android windows管理(一)

1、Android手机开机后,显示壁纸、桌面、状态栏

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

2、window type

3、壁纸window的添加过程

3.1 frameworks\base\core\java\android\view\WindowManager.java
java 复制代码
public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
3.2 frameworks\base\services\java\com\android\server\SystemServer.java
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");
    }
    ...
}
3.3 frameworks\base\services\core\java\com\android\server\wallpaper\WallpaperManagerService.java
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();
        }

connection.mService.attach

3.4 frameworks\base\core\java\android\service\wallpaper\WallpaperService.java
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;
    }
...
}

mSession.addToDisplay

3.5 frameworks\base\services\core\java\com\android\server\wm\Session.java
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);
    }

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

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) {
            }
3.6 小结

以上只是简单跟踪了一下wallpaper添加window的过程。

整个过程中涉及到比较多的类和流程,比较复杂。

对TYPE_WALLPAPER的window type进行了跟踪,没有对整个过程进行展开。

可以看出window的添加过程。window的创建、窗口参数。

相关推荐
开心呆哥2 分钟前
【如何使用 ADB 脚本批量停止 Android 设备上的所有应用】
android·adb
CYRUS STUDIO1 小时前
ARM64汇编寻址、汇编指令、指令编码方式
android·汇编·arm开发·arm·arm64
我不是李.杨1 小时前
Windows10/11开启卓越性能模式 windows开启卓越性能电源模式 工作电脑开启卓越性能模式 电脑开启性能模式
windows·电脑
weixin_449310842 小时前
高效集成:聚水潭采购数据同步到MySQL
android·数据库·mysql
Zender Han2 小时前
Flutter自定义矩形进度条实现详解
android·flutter·ios
Cachel wood2 小时前
Github配置ssh key原理及操作步骤
运维·开发语言·数据库·windows·postgresql·ssh·github
汪小敏同学2 小时前
【Django进阶】django-rest-framework中文文档——快速入门
网络·windows·oracle
白乐天_n4 小时前
adb:Android调试桥
android·adb
慕舟舟5 小时前
Windows密码的网络认证---基于挑战响应认证的NTLM协议
windows·网络安全
姑苏风8 小时前
《Kotlin实战》-附录
android·开发语言·kotlin