壁纸更新是一个壁纸服务,每换一张壁纸,就是将该图片写入壁纸文件,再启动一个壁纸服务读取该壁纸文件显示出来的过程
平台
Android 5.1
源代码路径
/frameworks/base/packages/SystemUI/src/com/android/systemui/
具体实现
显示流程
ImageWallpaper.java:
1 | /** |
updateSurfaceSize():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
41void updateSurfaceSize(SurfaceHolder surfaceHolder) {
Point p = getDefaultDisplaySize();
// Load background image dimensions, if we haven't saved them yet
if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
// Need to load the image to get dimensions
mWallpaperManager.forgetLoadedWallpaper();
// 加载壁纸图片
updateWallpaperLocked();
if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
// Default to the display size if we can't find the dimensions
mBackgroundWidth = p.x;
mBackgroundHeight = p.y;
}
}
// Force the wallpaper to cover the screen in both dimensions
int surfaceWidth = Math.max(p.x, mBackgroundWidth);
int surfaceHeight = Math.max(p.y, mBackgroundHeight);
// If the surface dimensions haven't changed, then just return
final Rect frame = surfaceHolder.getSurfaceFrame();
if (frame != null) {
final int dw = frame.width();
final int dh = frame.height();
if (surfaceWidth == dw && surfaceHeight == dh) {
return;
}
}
if (FIXED_SIZED_SURFACE) {
// 图片尺寸大则用图片尺寸,屏幕尺寸大则用屏幕尺寸
// 图片尺寸大时,滑动桌面时壁纸随之而动
// Used a fixed size surface, because we are special. We can do
// this because we know the current design of window animations doesn't
// cause this to break.
surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight);
} else {
surfaceHolder.setSizeFromLayout();
}
}
updateWallpaperLocked():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
31private void updateWallpaperLocked() {
Throwable exception = null;
try {
mBackground = null;
mBackgroundWidth = -1;
mBackgroundHeight = -1;
mBackground = mWallpaperManager.getBitmap();
mBackgroundWidth = mBackground.getWidth();
mBackgroundHeight = mBackground.getHeight();
} catch (RuntimeException e) {
exception = e;
} catch (OutOfMemoryError e) {
exception = e;
}
if (exception != null) {
mBackground = null;
mBackgroundWidth = -1;
mBackgroundHeight = -1;
// Note that if we do fail at this, and the default wallpaper can't
// be loaded, we will go into a cycle. Don't do a build where the
// default wallpaper can't be loaded.
Log.w(TAG, "Unable to load wallpaper!", exception);
try {
mWallpaperManager.clear();
} catch (IOException ex) {
// now we're really screwed.
Log.w(TAG, "Unable reset to default wallpaper!", ex);
}
}
}
getBitmap():1
2
3
4
5
6
7public Bitmap getBitmap() {
return getBitmapAsUser(mContext.getUserId());
}
public Bitmap getBitmapAsUser(int userId) {
return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId);
}
peekWallpaperBitmap():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
31public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which, int userId) {
synchronized (this) {
if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) {
return mCachedWallpaper;
}
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
try {
mCachedWallpaper = getCurrentWallpaperLocked(userId);
mCachedWallpaperUserId = userId;
} catch (OutOfMemoryError e) {
Log.w(TAG, "No memory load current wallpaper", e);
}
if (mCachedWallpaper != null) {
return mCachedWallpaper;
}
}
if (returnDefault) {
// 如果上面没有得到壁纸资源就在这里取得默认壁纸即路径com.android.internal.R.drawable.default_wallpaper并 把图片写入/data/system/users/{userid}/wallpaper
Bitmap defaultWallpaper = mDefaultWallpaper;
if (defaultWallpaper == null) {
defaultWallpaper = getDefaultWallpaper(context, which);
synchronized (this) {
mDefaultWallpaper = defaultWallpaper;
}
}
return defaultWallpaper;
}
return null;
}
getCurrentWallpaperLocked():
// 从路径data//system/users/{userid}/wallpaper取得当前用户壁纸,如果手机不是第一次启动这个一般能取到壁纸资源
1 | private Bitmap getCurrentWallpaperLocked(int userId) { |
drawFrame():
得到壁纸图片后开始绘制:
1 | void drawFrame() { |
设置流程
添加权限
1 | <uses-permission android:name="android.permission.SET_WALLPAPER"/> |
设置壁纸
1 | WallpaperManager wallpaperManager = WallpaperManager.getInstance(this); |
分析设置过程
setStream():
1 | try { |
WallpaperManagerService.java
setWallpaper():
1 | public ParcelFileDescriptor setWallpaper(String name, String callingPackage, |
onEvent():
监听壁纸图片变化的回调
1 | public void onEvent(int event, String path) { |
锁屏壁纸更新
notifyLockWallpaperChanged():
1 | void notifyLockWallpaperChanged() { |
LockscreenWallpaper.java:
1 | public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) { |
LockscreenWallpaper.java onWallpaperChanged:
1 | public void onWallpaperChanged() { |
run():
实现了 runnable 接口,异步获取壁纸图片,更新 statusbar
1 | public void run() { |
更新桌面壁纸
ImageWallpaper.java bindWallpaperComponentLocked():
1 | boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force, |
WallpaperConnection.java onServiceConnected():
ImageWallpaper 继承自 service,bindService,所以看 conn 的 onServiceConnected()
1 | public void onServiceConnected(ComponentName name, IBinder service) { |
attachServcieLocked():
1 | void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) { |
IWallpaperService.Stub attach():
1 | public void attach(IWallpaperConnection conn, IBinder windowToken, |
IWallpaperEngineWrapper IWallpaperEngineWrapper()
1 | Message msg = mCaller.obtainMessage(DO_ATTACH); |
1 | case DO_ATTACH: { |
ImageWallpaper.java onCreateEngine():
1 | public Engine onCreateEngine() { |
Engine.java attach():
1 | void attach(IWallpaperEngineWrapper wrapper) { |
ImageWallpaper.java onCreate():
1 | public void onCreate(SurfaceHolder surfaceHolder) { |
updateSurfaceSize():
见流程