-----------------------------------------------------------------------------------------------------------------------------------------------------

android10的壁纸显示流程已经和之前的不一样了,我也查了一些资料,然后结合自己看代码,最后找到了显示壁纸的地方了。只是静态壁纸。

packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java

不管是去设置壁纸还是当你休眠唤醒,都会走这里壁纸。

ImageWallpaperRenderer这个在ImageWallpaper中有调用,ImageWallpaper也需要一起看看。

packages/SystemUI/src/com/android/systemui/ImageWallpaper.java

-----------------------------------------------------------忽略,这个是壁纸显示相关的-----------------------------------------------------------------------

Wallpapers

长按桌面,选择wallpapers去设置壁纸,可以设置主屏,也可以设置锁屏,也可以同时设置。

/packages/apps/WallpaperPicker2/ 代码在这里。这里分析一下点了设置后的流程。

从桌面长按,然后选择wallpapers,然后选择一张图片,然后点击设置,这时候会有个对话框出来,让你选择设置的类型。Home screen / Lock screen / Home and Lock screen

这个avtivity代码在

/packages/apps/WallpaperPicker2/src/com/android/wallpaper/picker/PreviewActivity.java

我们主要看这个对话框的代码,这个对话框的代码在

/packages/apps/WallpaperPicker2/src/com/android/wallpaper/picker/SetWallpaperDialogFragment.java

    public Dialog onCreateDialog(Bundle savedInstanceState) {super.onCreateDialog(savedInstanceState);Context context = getContext();@SuppressWarnings("RestrictTo")View layout =View.inflate(new ContextThemeWrapper(getActivity(), R.style.LightDialogTheme),R.layout.dialog_set_wallpaper,null);AlertDialog dialog = new AlertDialog.Builder(context, R.style.LightDialogTheme).setTitle(mTitleResId).setView(layout).create();mSetHomeWallpaperButton = layout.findViewById(R.id.set_home_wallpaper_button);mSetHomeWallpaperButton.setOnClickListener(v -> {mListener.onSet(WallpaperPersister.DEST_HOME_SCREEN);dismiss();});ButtonDrawableSetterCompat.setDrawableToButtonStart(mSetHomeWallpaperButton,context.getDrawable(R.drawable.ic_home_24px));mSetLockWallpaperButton = layout.findViewById(R.id.set_lock_wallpaper_button);mSetLockWallpaperButton.setOnClickListener(v -> {mListener.onSet(WallpaperPersister.DEST_LOCK_SCREEN);dismiss();});ButtonDrawableSetterCompat.setDrawableToButtonStart(mSetLockWallpaperButton,context.getDrawable(R.drawable.ic_lock_outline_24px));mSetBothWallpaperButton = layout.findViewById(R.id.set_both_wallpaper_button);mSetBothWallpaperButton.setOnClickListener(v -> {mListener.onSet(WallpaperPersister.DEST_BOTH);dismiss();});ButtonDrawableSetterCompat.setDrawableToButtonStart(mSetBothWallpaperButton,context.getDrawable(R.drawable.ic_smartphone_24px));updateButtonsVisibility();return dialog;}

可以看到这里面就有3个button,对应的就是screen / Lock screen / Home and Lock screen,点击后就会调用onSet这个接口,下面就去追踪这个接口的实现。

这个接口实现的地方在

/packages/apps/WallpaperPicker2/src/com/android/wallpaper/picker/PreviewFragment.java

    @Overridepublic void onSet(int destination) {setCurrentWallpaper(destination);}/*** Sets current wallpaper to the device based on current zoom and scroll state.** @param destination The wallpaper destination i.e. home vs. lockscreen vs. both.*/private void setCurrentWallpaper(@Destination final int destination) {mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,destination, mFullResImageView.getScale(), calculateCropRect(),new SetWallpaperCallback() {@Overridepublic void onSuccess() {finishActivityWithResultOk();}@Overridepublic void onError(@Nullable Throwable throwable) {showSetWallpaperErrorDialog(destination);}});}

然后调用setCurrentWallpaper去设置壁纸。代码在

/packages/apps/WallpaperPicker2/src/com/android/module/WallpaperSetter.java

/*** Sets current wallpaper to the device based on current zoom and scroll state.** @param containerActivity main Activity that owns the current fragment* @param wallpaper info for the actual wallpaper to set* @param wallpaperAsset  Wallpaper asset from which to retrieve image data.* @param destination The wallpaper destination i.e. home vs. lockscreen vs. both.* @param wallpaperScale Scaling factor applied to the source image before setting the*                       wallpaper to the device.* @param cropRect Desired crop area of the wallpaper in post-scale units. If null, then the*                 wallpaper image will be set without any scaling or cropping.* @param callback optional callback to be notified when the wallpaper is set.*/public void setCurrentWallpaper(Activity containerActivity, WallpaperInfo wallpaper,Asset wallpaperAsset, @Destination final int destination, float wallpaperScale,@Nullable Rect cropRect, @Nullable SetWallpaperCallback callback) {if (wallpaper instanceof LiveWallpaperInfo) {setCurrentLiveWallpaper(containerActivity, (LiveWallpaperInfo) wallpaper, destination,callback);return;}mPreferences.setPendingWallpaperSetStatus(WallpaperPreferences.WALLPAPER_SET_PENDING);// Save current screen rotation so we can temporarily disable rotation while setting the// wallpaper and restore after setting the wallpaper finishes.saveAndLockScreenOrientation(containerActivity);// Clear MosaicView tiles and Glide's cache and pools to reclaim memory for final cropped// bitmap.Glide.get(containerActivity).clearMemory();// ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore// causes Espresso to hang once the dialog is shown.if (!mTestingModeEnabled && !containerActivity.isFinishing()) {int themeResId = (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP)? R.style.ProgressDialogThemePreL : R.style.LightDialogTheme;mProgressDialog = new ProgressDialog(containerActivity, themeResId);mProgressDialog.setTitle(PROGRESS_DIALOG_NO_TITLE);mProgressDialog.setMessage(containerActivity.getString(R.string.set_wallpaper_progress_message));mProgressDialog.setIndeterminate(PROGRESS_DIALOG_INDETERMINATE);mProgressDialog.show();}Log.i("a", "WallpaperSetter destination "+destination);mWallpaperPersister.setIndividualWallpaper(wallpaper, wallpaperAsset, cropRect,wallpaperScale, destination, new SetWallpaperCallback() {@Overridepublic void onSuccess() {onWallpaperApplied(wallpaper, containerActivity);if (callback != null) {callback.onSuccess();}}@Overridepublic void onError(Throwable throwable) {onWallpaperApplyError(throwable, containerActivity);if (callback != null) {callback.onError(throwable);}}});}

调用WallpaperPersister接口的setIndividualWallpaper方法去设置壁纸,实现的地方在。

/packages/apps/WallpaperPicker2/src/com/android/module/DefaultWallpaperPersister.java

@Overridepublic void setIndividualWallpaper(final WallpaperInfo wallpaper, Asset asset,@Nullable Rect cropRect, float scale, @Destination final int destination,final SetWallpaperCallback callback) {// Set wallpaper without downscaling directly from an input stream if there's no crop rect// specified by the caller and the asset is streamable.if (cropRect == null && asset instanceof StreamableAsset) {((StreamableAsset) asset).fetchInputStream(new StreamReceiver() {@Overridepublic void onInputStreamOpened(@Nullable InputStream inputStream) {if (inputStream == null) {callback.onError(null /* throwable */);return;}setIndividualWallpaper(wallpaper, inputStream, destination, callback);}});return;}// If no crop rect is specified but the wallpaper asset is not streamable, then fall back to// using the device's display size.if (cropRect == null) {Display display = ((WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(display);asset.decodeBitmap(screenSize.x, screenSize.y, new BitmapReceiver() {@Overridepublic void onBitmapDecoded(@Nullable Bitmap bitmap) {if (bitmap == null) {callback.onError(null /* throwable */);return;}setIndividualWallpaper(wallpaper, bitmap, destination, callback);}});return;}BitmapCropper bitmapCropper = InjectorProvider.getInjector().getBitmapCropper();bitmapCropper.cropAndScaleBitmap(asset, scale, cropRect, new Callback() {@Overridepublic void onBitmapCropped(Bitmap croppedBitmap) {setIndividualWallpaper(wallpaper, croppedBitmap, destination, callback);}@Overridepublic void onError(@Nullable Throwable e) {callback.onError(e);}});}

然后调用setIndividualWallpaper

    /*** Sets a static individual wallpaper stream to the system via the WallpaperManager.** @param wallpaper   Wallpaper model object.* @param inputStream JPEG or PNG stream of wallpaper image's bytes.* @param destination The destination - where to set the wallpaper to.* @param callback    Called once the wallpaper was set or if an error occurred.*/private void setIndividualWallpaper(WallpaperInfo wallpaper, InputStream inputStream,@Destination int destination, SetWallpaperCallback callback) {SetWallpaperTask setWallpaperTask =new SetWallpaperTask(wallpaper, inputStream, destination, callback);setWallpaperTask.execute();}

这里会开个线程去设置壁纸,然后追踪这个SetWallpaperTask

@Overrideprotected Boolean doInBackground(Void... unused) {int whichWallpaper;if (mDestination == DEST_HOME_SCREEN) {whichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM;} else if (mDestination == DEST_LOCK_SCREEN) {whichWallpaper = WallpaperManagerCompat.FLAG_LOCK;} else { // DEST_BOTHwhichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM| WallpaperManagerCompat.FLAG_LOCK;}Log.i("a", "DefaultWallpaperPersister mDestination whichWallpaper "+mDestination+" "+whichWallpaper);// NOTE: The rotating wallpaper component must be determined here, _before_ actually setting// the bitmap/stream on WallpaperManagerCompat, to ensure that the// RotatingWallpaperComponentChecker is doing its check while rotation is still enabled.// E.g., if "live wallpaper" is the component, then it needs to check while live wallpaper is// still set as the active wallpaper on the device. Otherwise, the checker would see a static// wallpaper is currently set and it would return the wrong value.@RotatingWallpaperComponent int currentRotatingWallpaperComponent =mRotatingWallpaperComponentChecker.getCurrentRotatingWallpaperComponent(mAppContext);boolean wasLockWallpaperSet = LockWallpaperStatusChecker.isLockWallpaperSet(mAppContext);boolean allowBackup = mWallpaper.getBackupPermission() == WallpaperInfo.BACKUP_ALLOWED;final int wallpaperId;if (mBitmap != null) {// Apply fill or stretch transformations on mBitmap if necessary.if (mFillSize != null) {mBitmap = BitmapTransformer.applyFillTransformation(mBitmap, mFillSize);}if (mStretchSize != null) {mBitmap = Bitmap.createScaledBitmap(mBitmap, mStretchSize.x, mStretchSize.y, true);}wallpaperId = setBitmapToWallpaperManagerCompat(mBitmap, allowBackup, whichWallpaper);} else if (mInputStream != null) {wallpaperId = setStreamToWallpaperManagerCompat(mInputStream, allowBackup, whichWallpaper);} else {Log.e(TAG, "Both the wallpaper bitmap and input stream are null so we're unable to set any "+ "kind of wallpaper here.");wallpaperId = 0;}if (wallpaperId > 0) {if (mDestination == DEST_HOME_SCREEN&& mWallpaperPreferences.getWallpaperPresentationMode()== WallpaperPreferences.PRESENTATION_MODE_ROTATING&& !wasLockWallpaperSet&& BuildCompat.isAtLeastN()) {Log.i("a", "DefaultWallpaperPersister 883");copyRotatingWallpaperToLock(currentRotatingWallpaperComponent);}setImageWallpaperMetadata(mDestination, wallpaperId);Log.i("a", "DefaultWallpaperPersister 887 wallpaperId "+wallpaperId);return true;} else {return false;}}

然后会走setBitmapToWallpaperManagerCompat,我这边设置的是图片,所以根据log,代码走这了。

    /*** Sets a wallpaper bitmap to the {@link WallpaperManagerCompat}.** @return an integer wallpaper ID. This is an actual wallpaper ID on N and later versions of* Android, otherwise on pre-N versions of Android will return a positive integer when the* operation was successful and zero if the operation encountered an error.*/private int setBitmapToWallpaperManagerCompat(Bitmap wallpaperBitmap, boolean allowBackup,int whichWallpaper) {ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();if (wallpaperBitmap.compress(CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {try {Log.i("a", "DefaultWallpaperPersister setBitmapToWallpaperManagerCompat 645 whichWallpaper "+whichWallpaper);byte[] outByteArray = tmpOut.toByteArray();return mWallpaperManagerCompat.setStream(new ByteArrayInputStream(outByteArray),null /* visibleCropHint */,allowBackup,whichWallpaper);} catch (IOException e) {Log.e(TAG, "unable to write stream to wallpaper manager");return 0;}} else {Log.e(TAG, "unable to compress wallpaper");Log.i("a", "DefaultWallpaperPersister setBitmapToWallpaperManagerCompat 658");try {return mWallpaperManagerCompat.setBitmap(wallpaperBitmap,null /* visibleCropHint */,allowBackup,whichWallpaper);} catch (IOException e) {Log.e(TAG, "unable to set wallpaper");return 0;}}}

然后会走接口WallpaperManagerCompat的setStream 或者setBitmap。

这里接口实现的地方我不确定在哪,

/packages/apps/WallpaperPicker2/src/com/android/compat/WallpaperManagerCompatV16.java

/packages/apps/WallpaperPicker2/src/com/android/compat/WallpaperManagerCompatVN.java

但是他们最后都会调用WallpaperManager的setStream和setBitmap。我们追踪WallpaperManager就行了。我追的是setBitmap。

/frameworks/base/core/java/android/app/WallpaperManager.java

/*** Like {@link #setBitmap(Bitmap, Rect, boolean, int)}, but allows to pass in an explicit user* id. If the user id doesn't match the user id the process is running under, calling this* requires permission {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.* @hide*/@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)public int setBitmap(Bitmap fullImage, Rect visibleCropHint,boolean allowBackup, @SetWallpaperFlags int which, int userId)throws IOException {validateRect(visibleCropHint);if (sGlobals.mService == null) {Log.w(TAG, "WallpaperService not running");throw new RuntimeException(new DeadSystemException());}final Bundle result = new Bundle();final WallpaperSetCompletion completion = new WallpaperSetCompletion();try {ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,mContext.getOpPackageName(), visibleCropHint, allowBackup,result, which, completion, userId);if (fd != null) {FileOutputStream fos = null;try {fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);fullImage.compress(Bitmap.CompressFormat.PNG, 90, fos);fos.close();completion.waitForCompletion();} finally {IoUtils.closeQuietly(fos);}}} catch (RemoteException e) {throw e.rethrowFromSystemServer();}return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);}

这里调用sGlobals.mService.setWallpaper去设置壁纸。这个mService就是IWallpaperManager,这边是用的AIDL的方法。所以我们去找WallpaperManagerService就能找到实现的地方,

/frameworks/base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java

@Overridepublic ParcelFileDescriptor setWallpaper(String name, String callingPackage,Rect cropHint, boolean allowBackup, Bundle extras, int which,IWallpaperManagerCallback completion, int userId) {userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,false /* all */, true /* full */, "changing wallpaper", null /* pkg */);checkPermission(android.Manifest.permission.SET_WALLPAPER);if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) {final String msg = "Must specify a valid wallpaper category to set";Slog.e(TAG, msg);throw new IllegalArgumentException(msg);}if (!isWallpaperSupported(callingPackage) || !isSetWallpaperAllowed(callingPackage)) {return null;}// "null" means the no-op crop, preserving the full input imageif (cropHint == null) {cropHint = new Rect(0, 0, 0, 0);} else {if (cropHint.isEmpty()|| cropHint.left < 0|| cropHint.top < 0) {throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);}}synchronized (mLock) {Slog.v("a", "setWallpaper which=0x" + Integer.toHexString(which));WallpaperData wallpaper;/* If we're setting system but not lock, and lock is currently sharing the system* wallpaper, we need to migrate that image over to being lock-only before* the caller here writes new bitmap data.*/if (which == FLAG_SYSTEM && mLockWallpaperMap.get(userId) == null) {Slog.i("a", "Migrating system->lock to preserve");migrateSystemToLockWallpaperLocked(userId);}wallpaper = getWallpaperSafeLocked(userId, which);Slog.v("a", "getWallpaperSafeLocked wallpaper.whichPending " + wallpaper.whichPending);final long ident = Binder.clearCallingIdentity();try {ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);if (pfd != null) {Slog.v("a", "updateWallpaperBitmapLocked wallpaper.whichPending " + wallpaper.whichPending);wallpaper.imageWallpaperPending = true;wallpaper.whichPending = which;wallpaper.setComplete = completion;wallpaper.cropHint.set(cropHint);wallpaper.allowBackup = allowBackup;}return pfd;} finally {Binder.restoreCallingIdentity(ident);}}}

注意一下migrateSystemToLockWallpaperLocked,如果你没设置过lock,并且你现在只去设置home,那么它会先把原先的home壁纸拷贝到lock壁纸,然后再去设置home。(如果这个migrateSystemToLockWallpaperLocked执行没成功的话,那么你会发现你设置了home壁纸,但是lock壁纸也变了。只有第一次有这种情况,之后设置不会,我遇到的。出现Can't migrate system wallpaper:异常了。)

下面没有继续追了。

Android 10 设置壁纸流程相关推荐

  1. Android 10 拨打电话流程

    接续上一章节,理解Android 10 拨打电话流程 packages/apps/Dialer/java/com/android/dialer/dialpadview/DialpadFragment. ...

  2. Android Wallpaper之设置壁纸流程

    What? 什么是壁纸? android wallpaper包括锁屏壁纸和桌面壁纸,壁纸又区分静态和动态两种.我们每天使用手机第一眼看到的就是壁纸,好看的壁纸对于手机的颜值也有大大的提升(滑稽),就让 ...

  3. Android Launcher 设置壁纸

    版本:1.0  日期:2014.11.25 2014.11.26 版权:©kince 特别推荐:泡在网上的日子 一.概述 一般Launcher都带有壁纸设置的功能,Android提供了设置壁纸的API ...

  4. android++设置壁纸,Android Launcher 设置壁纸

    如果是KitKat以下版本,那么会调用以下方法: int width = getWallpaperDesiredMinimumWidth(); int height = getWallpaperDes ...

  5. android蓝牙设置名称流程,Android 8 设置蓝牙名称 流程

    记录android 8设置蓝牙名称的流程.java packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDeviceR ...

  6. Android 10 设置kernel log level

    文章目录 查看平台默认kernel loglevel 关闭所有kernel log 修改kernel log默认值 printk文件解读 有时候kernel log内容过多/过少影响我们分析问题,因此 ...

  7. Android 设置壁纸流程

    W/InputManager-JNI: Input channel object '7d2a123 com.android.wallpaperpicker/com.android.wallpaperp ...

  8. android 壁纸设置成功,在Android上设置壁纸刷新

    我正在尝试更改当前的用户壁纸. 我已经设置了set_wallpaper权限,但它确实有效. 但是当我改变壁纸时,我必须等待大约15秒才能看到壁纸的变化. 这是很奇怪的,因为如果我检查锁定屏幕它已经改变 ...

  9. android 设置壁纸,Android 代码设置壁纸的方式,兼容各大ROM

    废话不多说,主要代码: public static void intent2SetWallPaper(Context context, String path) { Uri uriPath = get ...

最新文章

  1. 玩转 Python 爬虫,需要先知道这些
  2. Android获取顶部状态栏statusBar高度、底部导航栏navigationBar高度
  3. Dev-C++ 调试方法简明图文教程
  4. C++函数中那些不可以被声明为虚函数的函数
  5. Webclient UI上help center hyperlink的显示逻辑
  6. BZOJ 1845三角形面积并
  7. fetch 不是xhr_春招|前端2019应届春招:不是被大厂选,而是选大厂(字节跳动,美团,网易)...
  8. PHP判断客户端协议类型是否为https
  9. C++中继承的父类与子类的关系
  10. Python进阶-----类组合的方式完成授权
  11. python的jira库操作
  12. 约束满足问题(Constraint Satisfaction Problems——CSPs):回溯操作,向前检验,约束传播,局部搜索
  13. Ubuntu下mysql的配置
  14. HTTP协议详解+经典面试题
  15. G1垃圾回收器详细解读
  16. 钉钉API考勤打卡记录获取并存入数据库(python)
  17. [翻译]在Windows版或MacOS版的Microsoft Edge上安装一个谷歌浏览器拓展
  18. 利用hive源码解析sql查了哪些表哪些字段
  19. 分布式微服务学习总结——分布式微服务概述
  20. 开发者该如何抓住微信小游戏的风口?听Cocos创始人王哲详解(上篇)

热门文章

  1. 一篇带你了解如何使用纯前端类Excel表格构建现金流量表
  2. 典型环节的频率特性(建议收藏)
  3. c 工厂模式与mysql链接_工厂模式连接数据库
  4. AcWing 0x00. 语法基础课【Python3】版题解-顺序/判断/循环语句
  5. 《曾有一个人 爱我如生命》——普希金诗词
  6. 主题:程序的扩展性(BPL+DLL)
  7. 搭建一个SV验证环境(1)
  8. 【SV 基础】queue 的一些用法
  9. 关于javascript,[object,object]是什么?
  10. linux sipp 呼叫转移_基于SIP协议的呼叫转移功能实现.pdf