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的创建、窗口参数。