Discuz! Board
标题: 关于android壁纸的一些文章 [打印本页]
作者: zangcf 时间: 2016-5-2 22:07
标题: 关于android壁纸的一些文章
本帖最后由 zangcf 于 2016-5-2 22:34 编辑
Android WallpaperManager解析及BUG解决:::http://blog.csdn.net/zyplus/article/details/8260478
析壁纸机制分析:::http://blog.csdn.net/guoqifa29/article/details/40105839第8章 深入理解Android壁纸:::
http://blog.csdn.net/innost/article/details/47660645
作者: zangcf 时间: 2016-5-2 22:08
标题: 析壁纸机制分析
文章记录自己的学习过程,供日后参考。
第一部分:通信通道的建立
首先要知道壁纸设置的大体流程:上层应用调用wallpaperManager.setStream()或其他接口进行设置壁纸,WallpaperManagerService首先将壁纸copy到/data/system/user/0/目录下,WallpaperManagerService对该目录注册了一个WallpaperObserver,拷贝壁纸成功后会触发调用WallpaperObserver.onEvent()函数,onEvent()函数首先调用notifyCallbacksLocked()触发回调,然后再调用bindWallpaperComponentLocked()做进行进一步的壁纸更换。虽然整个壁纸机制有WallpaperManager、WallpaperService、ImageWallpaper、WallpaperManagerService、Globals、DrawableEngine、WallpaperData、WallpaperConnection等数据结构,感觉挺复杂的,我们应该剥离他的外表,看清他的本质。我们只要搞清了他们之间怎么交互的?交流些什么东西?就搞清楚了整个壁纸机制,说白了只要搞清楚IWallpaperService.aidl、IWallpaperEngine.aidl、IWallpaperConnection.aidl这三个文件就OK了,因为这三个文件是通信的关键所在。下面这张图代表了WallpaperService与WallpaperManagerService的交互关系。
[attach]197[/attach]
1.IWallpaperService.aidl
[html] view plain copy


- oneway interface IWallpaperService {
- void attach(IWallpaperConnection connection,
- IBinder windowToken, int windowType, boolean isPreview,
- int reqWidth, int reqHeight);
- }
aidl语言专为Binder设计,因此里面的函数可看做是通信接口。
(1).WallpaperService.IWallpaperServiceWrapper extends IWallpaperService.Stub;
(2).WallpaperService.onBind()
[html] view plain copy


- /**
- * Implement to return the implementation of the internal accessibility
- * service interface. Subclasses should not override.
- */
- @Override
- public final IBinder onBind(Intent intent) {
- return new IWallpaperServiceWrapper(this);
- }
从上面两点可以知道:IWallpaperService的Binder本地端在WallpaperService中;WallpaperService服务将是调用mContext.bindService()启动的;IWallpaperService的代理对象将在ServiceConnection.onServiceConnected()中获取。很容易验证WallPaperManagerService中确实是这么干的。
WallPaperManagerService.bindWallpaperComponentLocked():
[html] view plain copy


- boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
- boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
- ........
- Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
- ........
- WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
- intent.setComponent(componentName);
- intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
- com.android.internal.R.string.wallpaper_binding_label);
- intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
- mContext, 0,
- Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
- mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
- 0, null, new UserHandle(serviceUserId)));
- if (!mContext.bindServiceAsUser(intent, newConn,
- Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
- new UserHandle(serviceUserId))) {
- ..........
- }
- }
文章最开头就说了,每次设置壁纸都会调用bindWallpaperComponentLocked()函数,也就是说每次设置壁纸都会重新new WallpaperConnection,重新调用mContext.bindServiceAsUser()绑定启动WallpaperService,为啥要每次重新bind一次呢?防止systemUI挂掉,无法设置壁纸?不管了,反正记住每次设置壁纸时都会bind一次WallpaperService,并且调用WallpaperConnection.onServiceConnected()函数。onServiceConnected()函数中真的获取了IWallpaperService的Binder代理对象。
[html] view plain copy


- public void onServiceConnected(ComponentName name, IBinder service) {
- synchronized (mLock) {
- if (mWallpaper.connection == this) {
- mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
- mService = IWallpaperService.Stub.asInterface(service);
- attachServiceLocked(this, mWallpaper);
- // XXX should probably do saveSettingsLocked() later
- // when we have an engine, but I'm not sure about
- // locking there and anyway we always need to be able to
- // recover if there is something wrong.
- saveSettingsLocked(mWallpaper);
- }
- }
- }
mService = IWallpaperService.Stub.asInterface(service);语句获取了IWallpaperService的Binder代理对象。再看看WallpaperConnection.onServiceConnected()函数中调用WallPaperManagerService.attachServiceLocked()干什么?
[html] view plain copy


- void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
- try {
- conn.mService.attach(conn, conn.mToken,
- WindowManager.LayoutParams.TYPE_WALLPAPER, false,
- wallpaper.width, wallpaper.height);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
- if (!wallpaper.wallpaperUpdating) {
- bindWallpaperComponentLocked(null, false, false, wallpaper, null);
- }
- }
- }
嗯,跨Binder调用IWallpaperService本地端的attach()。看看attach()做了什么?
[html] view plain copy


- public void attach(IWallpaperConnection conn, IBinder windowToken,
- int windowType, boolean isPreview, int reqWidth, int reqHeight) {
- new IWallpaperEngineWrapper(mTarget, conn, windowToken,
- windowType, isPreview, reqWidth, reqHeight);
- }
直接new IWallpaperEngineWrapper对象,注意传进来的参数,包含壁纸显示参数。IWallpaperEngineWrapper extends IWallpaperEngine.Stub implements HandlerCaller.Callback,所以又知道了IWallpaperEngine的Binder本地端保存在WallpaperService中,代理端返回给WallPaperManagerService.WallpaperConnection.mEngine变量的呢?这个研究到后边应该自然就知道了。IWallpaperEngineWrapper的构造函数将被调用,在构造函数中会post一个handle消息DO_ATTACH,然后消息在executeMessage()中执行:
[html] view plain copy


- switch (message.what) {
- case DO_ATTACH: {
- try {
- mConnection.attachEngine(this);
- } catch (RemoteException e) {
- Log.w(TAG, "Wallpaper host disappeared", e);
- return;
- }
- Engine engine = onCreateEngine();
- mEngine = engine;
- mActiveEngines.add(engine);
- engine.attach(this);
- return;
- }
感觉牵涉的越来越多了,没关系,一个个来分析。mConnection的值从attach()函数的参数获取,很容易知道就是IWallpaperConnection的Binder代理对象,本地对象就是WallpaperConnection,在WallpaperManagerService中。上面代码调用mConnection.attachEngine(this), this指向IWallpaperEngineWrapper,说白了就是把IWallpaperEngine的Binder代理对象传给WallpaperManagerService,至此,WallpaperManagerService与WallpaperService的三条Binder通信通道全部建立起来了。
总结:设置壁纸时,触发调用WallpaperManagerService.bindWallpaperComponentLocked(),函数会bindService(WallpaperService),在bind过程中WallpaperService返回一个IWallpaperService的代理对象给WallpaperManagerService,WallpaperManagerService侧接着调用IWallpaperService.attach()函数将WallpaperManagerService侧的IWallpaperConnection代理对象传给WallpaperService,WallpaperService侧同时也会调用刚传过来的IWallpaperConnection.attachEngine()将IWallpaperEngine的代理对象传过去。嗯,有点乱。
从上面的图中,看出现在attach()、attachEngine()两个函数光荣地完成了使命。下面来分析engineShown()、setDesiredSize()、setVisibility()、dispatchPointer()、dispatchWallpaperCommand()五个函数。
1.engineShown()
先看下这个函数的实现:
[html] view plain copy


- public void engineShown(IWallpaperEngine engine) {
- synchronized (mLock) {
- if (mReply != null) {
- long ident = Binder.clearCallingIdentity();
- try {
- mReply.sendResult(null);
- } catch (RemoteException e) {
- Binder.restoreCallingIdentity(ident);
- }
- mReply = null;
- }
- }
- }
mReply是从bindWallpaperComponentLocked()函数的参数赋值的,是个null。所以这个函数基本没干什么,但是可以通过名字知道,WallpaperService这边将壁纸显示成功后会调用这个函数。那就研究下在哪里调用engineShown(),这样可以反推显示等逻辑所在的地方。嗯,engineShown()在IWallpaperEngineWrapper.reportShown()中调用。
[html] view plain copy


- public void reportShown() {
- if (!mShownReported) {
- mShownReported = true;
- try {
- mConnection.engineShown(this);
- } catch (RemoteException e) {
- Log.w(TAG, "Wallpaper host disappeared", e);
- return;
- }
- }
- }
再看看reportShown()在哪调用,发现在updateSurface()中调用,浏览下updateSurface()函数,可以肯定壁纸刷新就在updateSurface()中完成。哈哈,下面来研究这个updateSurface()函数。
这个函数在很多地方调用,可以看做是壁纸刷新函数。
[html] view plain copy


- void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
- if (mDestroyed) {
- Log.w(TAG, "Ignoring updateSurface: destroyed");
- }
-
- int myWidth = mSurfaceHolder.getRequestedWidth();
- if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
- int myHeight = mSurfaceHolder.getRequestedHeight();
- if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
-
- final boolean creating = !mCreated;
- final boolean surfaceCreating = !mSurfaceCreated;
- final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
- boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
- final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
- final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
- mCurWindowPrivateFlags != mWindowPrivateFlags;
- if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
- || typeChanged || flagsChanged || redrawNeeded
- || !mIWallpaperEngine.mShownReported) {
-
- if (DEBUG) Log.v(TAG, "Changes: creating=" + creating
- + " format=" + formatChanged + " size=" + sizeChanged);
-
- try {
- mWidth = myWidth;
- mHeight = myHeight;
- mFormat = mSurfaceHolder.getRequestedFormat();
- mType = mSurfaceHolder.getRequestedType();
-
- mLayout.x = 0;
- mLayout.y = 0;
- mLayout.width = myWidth;
- mLayout.height = myHeight;
-
- mLayout.format = mFormat;
-
- mCurWindowFlags = mWindowFlags;
- mLayout.flags = mWindowFlags
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- ;
- mCurWindowPrivateFlags = mWindowPrivateFlags;
- mLayout.privateFlags = mWindowPrivateFlags;
-
- mLayout.memoryType = mType;
- mLayout.token = mWindowToken;
-
- if (!mCreated) { //创建输入通道、addToDisplay()、创建一个触摸事件接受者;
- mLayout.type = mIWallpaperEngine.mWindowType;
- mLayout.gravity = Gravity.START|Gravity.TOP;
- mLayout.setTitle(WallpaperService.this.getClass().getName());
- mLayout.windowAnimations =
- com.android.internal.R.style.Animation_Wallpaper;
- mInputChannel = new InputChannel();
- if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
- Display.DEFAULT_DISPLAY, mContentInsets, mInputChannel) < 0) {
- Log.w(TAG, "Failed to add window while updating wallpaper surface.");
- return;
- }
- mCreated = true;
-
- mInputEventReceiver = new WallpaperInputEventReceiver(
- mInputChannel, Looper.myLooper());
- }
-
- mSurfaceHolder.mSurfaceLock.lock();
- mDrawingAllowed = true;
-
- final int relayoutResult = mSession.relayout( //relayout();
- mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
- View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
- mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
-
- if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
- + ", frame=" + mWinFrame);
-
- int w = mWinFrame.width();
- if (mCurWidth != w) {
- sizeChanged = true;
- mCurWidth = w;
- }
- int h = mWinFrame.height();
- if (mCurHeight != h) {
- sizeChanged = true;
- mCurHeight = h;
- }
-
- mSurfaceHolder.setSurfaceFrameSize(w, h); //设置surface Frame Size;
- mSurfaceHolder.mSurfaceLock.unlock();
-
- if (!mSurfaceHolder.mSurface.isValid()) {
- reportSurfaceDestroyed();
- if (DEBUG) Log.v(TAG, "Layout: Surface destroyed");
- return;
- }
-
- boolean didSurface = false;
-
- try {
- mSurfaceHolder.ungetCallbacks();
-
- if (surfaceCreating) {
- mIsCreating = true;
- didSurface = true;
- if (DEBUG) Log.v(TAG, "onSurfaceCreated("
- + mSurfaceHolder + "): " + this);
- onSurfaceCreated(mSurfaceHolder); //创建surface;
- SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
- if (callbacks != null) {
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceCreated(mSurfaceHolder);
- }
- }
- }
-
- redrawNeeded |= creating || (relayoutResult
- & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
-
- if (forceReport || creating || surfaceCreating
- || formatChanged || sizeChanged) {
- if (DEBUG) {
- RuntimeException e = new RuntimeException();
- e.fillInStackTrace();
- Log.w(TAG, "forceReport=" + forceReport + " creating=" + creating
- + " formatChanged=" + formatChanged
- + " sizeChanged=" + sizeChanged, e);
- }
- if (DEBUG) Log.v(TAG, "onSurfaceChanged("
- + mSurfaceHolder + ", " + mFormat
- + ", " + mCurWidth + ", " + mCurHeight
- + "): " + this);
- didSurface = true;
- onSurfaceChanged(mSurfaceHolder, mFormat,
- mCurWidth, mCurHeight);
- SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
- if (callbacks != null) {
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceChanged(mSurfaceHolder, mFormat,
- mCurWidth, mCurHeight);
- }
- }
- }
-
- if (redrawNeeded) {
- onSurfaceRedrawNeeded(mSurfaceHolder);
- SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
- if (callbacks != null) {
- for (SurfaceHolder.Callback c : callbacks) {
- if (c instanceof SurfaceHolder.Callback2) {
- ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
- mSurfaceHolder);
- }
- }
- }
- }
-
- if (didSurface && !mReportedVisible) {
- // This wallpaper is currently invisible, but its
- // surface has changed. At this point let's tell it
- // again that it is invisible in case the report about
- // the surface caused it to start running. We really
- // don't want wallpapers running when not visible.
- if (mIsCreating) {
- // Some wallpapers will ignore this call if they
- // had previously been told they were invisble,
- // so if we are creating a new surface then toggle surface
- // the state to get them to notice.
- if (DEBUG) Log.v(TAG, "onVisibilityChanged(true) at surface: "
- + this);
- onVisibilityChanged(true);
- }
- if (DEBUG) Log.v(TAG, "onVisibilityChanged(false) at surface: "
- + this);
- onVisibilityChanged(false);
- }
-
- } finally {
- mIsCreating = false;
- mSurfaceCreated = true;
- if (redrawNeeded) {
- mSession.finishDrawing(mWindow);
- }
- mIWallpaperEngine.reportShown();
- }
- } catch (RemoteException ex) {
- }
- if (DEBUG) Log.v(
- TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
- " w=" + mLayout.width + " h=" + mLayout.height);
- }
- }
2.setDesiredSize()
没啥用的一个函数。
3.setVisibility()
没看到有调用。
4.dispatchPointer()
接受触摸事件。动态壁纸需要接受触摸事件。
第二部分:设置一张壁纸WallpaperService中的调用逻辑
1.DO_DETACH
从WallpaperManagerService.detachWallpaperLocked()-->IWallpaperEngineWrapper.destroy()-->Engine.detach()
a.mSession.remove(mWindow);---------------------移除壁纸窗口;
b.mSurfaceHolder.mSurface.release();------------释放surface;
c.mInputChannel.dispose();--------------------------关闭输入通道;
主要做了三件事:remove窗口;释放surface;关闭输入通道;
2.DO_ATTACH
从WallpaperManagerService.attachServiceLocked()-->IWallpaperService.attach()
a.mSurfaceHolder.setSizeFromLayout();--------------------------------重置surface的尺寸为(-1,-1);
b.mSession = WindowManagerGlobal.getWindowSession();-------获取WindowSession;
c.registerReceiver(mReceiver, filter);--------------------------------------注册ACTION_SCREEN_ON和ACTION_SCREEN_OFF广播接收器;
d.Engine.onCreate(mSurfaceHolder);-->updateSurfaceSize():
1).mWallpaperManager.forgetLoadedWallpaper();------------------清除mWallpaper和mDefaultWallpaper值;
2).updateWallpaperLocked();-->mBackground = mWallpaperManager.getBitmap();-----------获取壁纸赋给mBackground;
3).surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight);----从mBackground中取值来修正surface的大小;
e.updateSurface(false, false, false);----------------------------------------因为前面清除了surface,所以这个函数肯定会重新new Surface;
1). mInputChannel = new InputChannel();
2).mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,Display.DEFAULT_DISPLAY, mContentInsets, mInputChannel);
3).mInputEventReceiver = new WallpaperInputEventReceiver(mInputChannel, Looper.myLooper());
4).mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
5).mSurfaceHolder.setSurfaceFrameSize(w, h);
6).onSurfaceCreated(mSurfaceHolder);
7).onSurfaceChanged(mSurfaceHolder, mFormat, mCurWidth, mCurHeight); drawFrame();
8).onSurfaceRedrawNeeded(mSurfaceHolder); drawFrame();
9)onVisibilityChanged(true); drawFrame();
3.MSG_UPDATE_SURFACE
a.mEngine.updateSurface(true, false, false)
1).mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
2).mSurfaceHolder.setSurfaceFrameSize(w, h);
4.MSG_WINDOW_RESIZED
a.mEngine.updateSurface(true, false, reportDraw);
1).mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface);
2).mSurfaceHolder.setSurfaceFrameSize(w, h);
3).onSurfaceRedrawNeeded(mSurfaceHolder);
4)mSession.finishDrawing(mWindow);
b.mEngine.doOffsetsChanged(true);----------没做什么;
总结:从上面的逻辑看,壁纸这块逻辑代码写的比较乱。
作者: zangcf 时间: 2016-5-2 23:50
最后的解决方法是修改WallpaperService.java这个文件:
void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
Log.w("zcfdebug", "updateSurface in WallpaperService!");
if (mDestroyed) {
Log.w(TAG, "Ignoring updateSurface: destroyed");
}
boolean fixedSize = false;
int myWidth = mSurfaceHolder.getRequestedWidth();
if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
else fixedSize = true;
int myHeight = mSurfaceHolder.getRequestedHeight();
if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
else fixedSize = true;
final boolean creating = !mCreated;
final boolean surfaceCreating = !mSurfaceCreated;
final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
boolean insetsChanged = !mCreated;
final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
mCurWindowPrivateFlags != mWindowPrivateFlags;
if (forceRelayout || creating || surfaceCreating || formatChanged || sizeChanged
|| typeChanged || flagsChanged || redrawNeeded
|| !mIWallpaperEngine.mShownReported) {
if (DEBUG) Log.v(TAG, "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged);
try {
mWidth = myWidth;
mHeight = myHeight;
mFormat = mSurfaceHolder.getRequestedFormat();
mType = mSurfaceHolder.getRequestedType();
mLayout.x = 0;
mLayout.y = 0;
//zcfdebug++<<
mLayout.x = 0;
mLayout.y = 260;
//zcfdebug>>++
mLayout.width = myWidth;
mLayout.height = myHeight;
mLayout.height = 560; //zcfdebug++
mLayout.format = mFormat;
mCurWindowFlags = mWindowFlags;
mLayout.flags = mWindowFlags
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
;
mCurWindowPrivateFlags = mWindowPrivateFlags;
mLayout.privateFlags = mWindowPrivateFlags;
mLayout.memoryType = mType;
mLayout.token = mWindowToken;
if (!mCreated) {
// Retrieve watch round and outset info
final WindowManager windowService = (WindowManager)getSystemService(
Context.WINDOW_SERVICE);
TypedArray windowStyle = obtainStyledAttributes(
com.android.internal.R.styleable.Window);
final Display display = windowService.getDefaultDisplay();
final boolean shouldUseBottomOutset =
display.getDisplayId() == Display.DEFAULT_DISPLAY;
if (shouldUseBottomOutset && windowStyle.hasValue(
R.styleable.Window_windowOutsetBottom)) {
if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
windowStyle.getValue(R.styleable.Window_windowOutsetBottom,
mOutsetBottom);
} else {
mOutsetBottom = null;
}
mWindowIsRound = getResources().getBoolean(
com.android.internal.R.bool.config_windowIsRound);
windowStyle.recycle();
// detect emulator
mIsEmulator = Build.HARDWARE.contains("goldfish");
mIsCircularEmulator = SystemProperties.getBoolean(
ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR, false);
// mIsCircularEmulator = false; // @todo L-MARK by ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR is private
// Add window
mLayout.type = mIWallpaperEngine.mWindowType;
mLayout.gravity = Gravity.START|Gravity.TOP;
mLayout.setTitle(WallpaperService.this.getClass().getName());
mLayout.windowAnimations =
com.android.internal.R.style.Animation_Wallpaper;
mInputChannel = new InputChannel();
if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
Display.DEFAULT_DISPLAY, mContentInsets, mInputChannel) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
}
mCreated = true;
mInputEventReceiver = new WallpaperInputEventReceiver(
mInputChannel, Looper.myLooper());
}
mSurfaceHolder.mSurfaceLock.lock();
mDrawingAllowed = true;
if (!fixedSize) {
mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding);
} else {
mLayout.surfaceInsets.set(0, 0, 0, 0);
}
mHeight=560;//zcfdebug++
final int relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mConfiguration, mSurfaceHolder.mSurface);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
int w = mWinFrame.width();
int h = mWinFrame.height();
if (!fixedSize) {
final Rect padding = mIWallpaperEngine.mDisplayPadding;
w += padding.left + padding.right;
h += padding.top + padding.bottom;
mOverscanInsets.left += padding.left;
mOverscanInsets.top += padding.top;
mOverscanInsets.right += padding.right;
mOverscanInsets.bottom += padding.bottom;
mContentInsets.left += padding.left;
mContentInsets.top += padding.top;
mContentInsets.right += padding.right;
mContentInsets.bottom += padding.bottom;
mStableInsets.left += padding.left;
mStableInsets.top += padding.top;
mStableInsets.right += padding.right;
mStableInsets.bottom += padding.bottom;
}
if (mCurWidth != w) {
sizeChanged = true;
mCurWidth = w;
}
if (mCurHeight != h) {
sizeChanged = true;
mCurHeight = h;
}
insetsChanged |= !mDispatchedOverscanInsets.equals(mOverscanInsets);
insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets);
insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets);
mSurfaceHolder.setSurfaceFrameSize(w, h);
mSurfaceHolder.mSurfaceLock.unlock();
if (!mSurfaceHolder.mSurface.isValid()) {
reportSurfaceDestroyed();
if (DEBUG) Log.v(TAG, "Layout: Surface destroyed");
return;
}
boolean didSurface = false;
try {
mSurfaceHolder.ungetCallbacks();
if (surfaceCreating) {
mIsCreating = true;
didSurface = true;
if (DEBUG) Log.v(TAG, "onSurfaceCreated("
+ mSurfaceHolder + "): " + this);
onSurfaceCreated(mSurfaceHolder);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
if (callbacks != null) {
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceCreated(mSurfaceHolder);
}
}
}
redrawNeeded |= creating || (relayoutResult
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
if (forceReport || creating || surfaceCreating
|| formatChanged || sizeChanged) {
if (DEBUG) {
RuntimeException e = new RuntimeException();
e.fillInStackTrace();
Log.w(TAG, "forceReport=" + forceReport + " creating=" + creating
+ " formatChanged=" + formatChanged
+ " sizeChanged=" + sizeChanged, e);
}
if (DEBUG) Log.v(TAG, "onSurfaceChanged("
+ mSurfaceHolder + ", " + mFormat
+ ", " + mCurWidth + ", " + mCurHeight
+ "): " + this);
didSurface = true;
onSurfaceChanged(mSurfaceHolder, mFormat,
mCurWidth, mCurHeight);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
if (callbacks != null) {
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceChanged(mSurfaceHolder, mFormat,
mCurWidth, mCurHeight);
}
}
}
if (insetsChanged) {
mDispatchedOverscanInsets.set(mOverscanInsets);
mDispatchedContentInsets.set(mContentInsets);
mDispatchedStableInsets.set(mStableInsets);
final boolean isRound = (mIsEmulator && mIsCircularEmulator)
|| mWindowIsRound;
mFinalSystemInsets.set(mDispatchedOverscanInsets);
mFinalStableInsets.set(mDispatchedStableInsets);
if (mOutsetBottom != null) {
final DisplayMetrics metrics = getResources().getDisplayMetrics();
mFinalSystemInsets.bottom =
( (int) mOutsetBottom.getDimension(metrics) )
+ mIWallpaperEngine.mDisplayPadding.bottom;
}
WindowInsets insets = new WindowInsets(mFinalSystemInsets,
null, mFinalStableInsets, isRound);
onApplyWindowInsets(insets);
}
if (redrawNeeded) {
onSurfaceRedrawNeeded(mSurfaceHolder);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
if (callbacks != null) {
for (SurfaceHolder.Callback c : callbacks) {
if (c instanceof SurfaceHolder.Callback2) {
((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
mSurfaceHolder);
}
}
}
}
if (didSurface && !mReportedVisible) {
// This wallpaper is currently invisible, but its
// surface has changed. At this point let's tell it
// again that it is invisible in case the report about
// the surface caused it to start running. We really
// don't want wallpapers running when not visible.
if (mIsCreating) {
// Some wallpapers will ignore this call if they
// had previously been told they were invisble,
// so if we are creating a new surface then toggle
// the state to get them to notice.
if (DEBUG) Log.v(TAG, "onVisibilityChanged(true) at surface: "
+ this);
onVisibilityChanged(true);
}
if (DEBUG) Log.v(TAG, "onVisibilityChanged(false) at surface: "
+ this);
onVisibilityChanged(false);
}
} finally {
mIsCreating = false;
mSurfaceCreated = true;
if (redrawNeeded) {
mSession.finishDrawing(mWindow);
}
mIWallpaperEngine.reportShown();
}
} catch (RemoteException ex) {
}
if (DEBUG) Log.v(
TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
" w=" + mLayout.width + " h=" + mLayout.height);
}
}
| 欢迎光临 Discuz! Board (http://47.89.242.157:9000/bbs/discuz/) |
Powered by Discuz! X3.2 |