WallpaperPicker2壁纸设置流程

WallpaperPicker2壁纸设置流程

参考链接
路径:alps/packages/apps/WallpaperPicker2
初始化三个按钮,设置监听SetWallpaperDialogFragment#onCreateDialog

 public Dialog onCreateDialog(Bundle savedInstanceState) {
    ...
mSetHomeWallpaperButton = layout.findViewById(R.id.set_home_wallpaper_button);
        mSetHomeWallpaperButton.setOnClickListener(
                v -> onSetWallpaperButtonClick(WallpaperPersister.DEST_HOME_SCREEN));
        ButtonDrawableSetterCompat.setDrawableToButtonStart(
                mSetHomeWallpaperButton,
                context.getDrawable(R.drawable.ic_home_24px));

        mSetLockWallpaperButton = layout.findViewById(R.id.set_lock_wallpaper_button);
        mSetLockWallpaperButton.setOnClickListener(
                v -> onSetWallpaperButtonClick(WallpaperPersister.DEST_LOCK_SCREEN));
        ButtonDrawableSetterCompat.setDrawableToButtonStart(
                mSetLockWallpaperButton,
                context.getDrawable(R.drawable.ic_lock_outline_24px));

        mSetBothWallpaperButton = layout.findViewById(R.id.set_both_wallpaper_button);
        mSetBothWallpaperButton.setOnClickListener(
                v -> onSetWallpaperButtonClick(WallpaperPersister.DEST_BOTH));
        ButtonDrawableSetterCompat.setDrawableToButtonStart(
                mSetBothWallpaperButton,
                context.getDrawable(R.drawable.ic_smartphone_24px));
    ...
    }

三个按钮事件,触发回调 SetWallpaperDialogFragment#onSetWallpaperButtonClick

  private void onSetWallpaperButtonClick(int destination) {
        mWithItemSelected = true;
        mListener.onSet(destination); //回调
        dismiss();
    }

回调实现PreviewFragment#onSet

public void onSet(int destination) {
        setCurrentWallpaper(destination);
    }

继续查看setCurrentWallpaper

    /**
     * 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.
     */
    protected abstract void setCurrentWallpaper(@Destination int destination);

有两处实现的位置:
1.继续追踪实现抽象方法的位置ImagePreviewFragment#setCurrentWallpaper

 @Override
    protected void setCurrentWallpaper(@Destination int destination) {
        if (getActivity() == null) {
            Log.w(TAG, "The activity is null, so don't set wallpaper!");
            return;
        }
        //使用父类PreviewFragment中初始化的>>==mWallpaperSetter==<< 
        >>==>>++mWallpaperSetter++<<==<<.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
                destination, mFullResImageView.getScale(), calculateCropRect(),
                new SetWallpaperCallback() {
                    @Override
                    public void onSuccess(WallpaperInfo wallpaperInfo) {
                        finishActivityWithResultOk();
                    }

                    @Override
                    public void onError(@Nullable Throwable throwable) {
                        showSetWallpaperErrorDialog(destination);
                    }
                });
    }

2.继续追踪实现抽象方法的位置PicturePreviewFragment#setCurrentWallpaper

 @Override
    protected void setCurrentWallpaper(int destination) {
        Rect cropRect = new Rect();
        mCropScale = calculateCropRectAndScale(cropRect);
       //使用父类PreviewFragment中初始化的>>==mWallpaperSetter==<< 
        >>==>>++mWallpaperSetter++<<==<<.setCurrentWallpaper(getActivity(), mWallpaper, mWallpaperAsset,
                destination, mCropScale, cropRect, new WallpaperPersister.SetWallpaperCallback() {
                    @Override
                    public void onSuccess(WallpaperInfo wallpaperInfo) {
                        finishActivityWithResultOk();
                    }

                    @Override
                    public void onError(@Nullable Throwable throwable) {
                        showSetWallpaperErrorDialog(destination);
                    }
                });
    }

具体是使用哪个类中的setCurrentWallpaper方法呢,通过查看在实例化PreviewFragment地方,结果为通过三元表达式判断是哪个子类,根据实例化的子类的类型判断是执行了哪个setCurrentWallpaper方法

 public static PreviewFragment newInstance(
            WallpaperInfo wallpaperInfo, @PreviewMode int mode, boolean testingModeEnabled) {

        boolean isLive = wallpaperInfo instanceof LiveWallpaperInfo;

        Bundle args = new Bundle();
        args.putParcelable(ARG_WALLPAPER, wallpaperInfo);
        args.putInt(ARG_PREVIEW_MODE, mode);
        args.putBoolean(ARG_TESTING_MODE_ENABLED, testingModeEnabled);

        >>==PreviewFragment fragment = isLive ? new LivePreviewFragment() :
                Flags.SPRD_WALLPAPER_STYLE_OPTION_ENABLED ?
                        new PicturePreviewFragment() : new ImagePreviewFragment();==<<
        fragment.setArguments(args);
        return fragment;
    }

Flags继承自BaseFlags

abstract class BaseFlags {
    public static boolean skipDailyWallpaperButtonEnabled = true;
    public static boolean desktopUiEnabled = false;
    public static boolean dynamicStartRotationTileEnabled = true;
    public static boolean stagingBackdropContentEnabled = false;
    public static boolean performanceMonitoringEnabled = true;

    public static final boolean SPRD_ENABLE_LOCK_WALLPAPER =
            SystemPropertiesUtils.getBoolean("ro.lockwallpaper.enable", true);

    public static boolean SPRD_STABLE_WALLPAPER =
            SystemPropertiesUtils.getBoolean("ro.wallpaper.stable", false);

    public static boolean SPRD_WALLPAPER_STYLE_OPTION_ENABLED =
            !SPRD_STABLE_WALLPAPER &&
            SystemPropertiesUtils.getBoolean("ro.wallpaper.style.enable", true);

    public static final boolean DEBUG =
            SystemPropertiesUtils.getBoolean("persist.sys.wallpaper.debug", false);
}

查看WallpaperSetter类中的setCurrentWallpaper实现方法

/**
     * Sets current wallpaper to the device with the minimum scale to fit the screen size.
     *
     * @param containerActivity main Activity that owns the current fragment
     * @param wallpaper info for the actual wallpaper to set
     * @param destination the wallpaper destination i.e. home vs. lockscreen vs. both.
     * @param callback optional callback to be notified when the wallpaper is set.
     */
    public void setCurrentWallpaper(Activity containerActivity, WallpaperInfo wallpaper,
                                    @Destination final int destination,
                                    @Nullable SetWallpaperCallback callback) {
        Asset wallpaperAsset = wallpaper.getAsset(containerActivity.getApplicationContext());
        wallpaperAsset.decodeRawDimensions(containerActivity, dimensions -> {
            if (dimensions == null) {
                Log.e(TAG, "Raw wallpaper's dimensions are null");
                return;
            }

            Display defaultDisplay = containerActivity.getWindowManager().getDefaultDisplay();
            Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(defaultDisplay);
            Rect visibleRawWallpaperRect =
                    WallpaperCropUtils.calculateVisibleRect(dimensions, screenSize);
            float wallpaperScale = WallpaperCropUtils.calculateMinZoom(dimensions, screenSize);
            Rect cropRect = WallpaperCropUtils.calculateCropRect(
                    containerActivity.getApplicationContext(), defaultDisplay,
                    dimensions, visibleRawWallpaperRect, wallpaperScale);

            setCurrentWallpaper(containerActivity, wallpaper, wallpaperAsset, destination,
                    wallpaperScale, cropRect, callback);
        });
    }

    /**
     * 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,
            @Nullable 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.
        saveAndLockScreenOrientationIfNeeded(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();
        }

        >>==mWallpaperPersister.setIndividualWallpaper(==<<
                wallpaper, wallpaperAsset, cropRect,
                wallpaperScale, destination, new SetWallpaperCallback() {
                    @Override
                    public void onSuccess(WallpaperInfo wallpaperInfo) {
                        onWallpaperApplied(wallpaper, containerActivity);
                        if (callback != null) {
                            callback.onSuccess(wallpaper);
                        }
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        onWallpaperApplyError(throwable, containerActivity);
                        if (callback != null) {
                            callback.onError(throwable);
                        }
                    }
                });
    }

//设置动态壁纸
    public void setCurrentLiveWallpaper(Activity activity, LiveWallpaperInfo wallpaper,
            @Destination final int destination, @Nullable SetWallpaperCallback callback) {
        try {
            // Save current screen rotation so we can temporarily disable rotation while setting the
            // wallpaper and restore after setting the wallpaper finishes.
            saveAndLockScreenOrientationIfNeeded(activity);

            if (destination == WallpaperPersister.DEST_LOCK_SCREEN) {
                throw new IllegalArgumentException(
                        "Live wallpaper cannot be applied on lock screen only");
            }
            WallpaperManager wallpaperManager = WallpaperManager.getInstance(activity);
            wallpaperManager.setWallpaperComponent(
                    wallpaper.getWallpaperComponent().getComponent());
            wallpaperManager.setWallpaperOffsetSteps(0.5f /* xStep */, 0.0f /* yStep */);
            wallpaperManager.setWallpaperOffsets(
                    activity.getWindow().getDecorView().getRootView().getWindowToken(),
                    0.5f /* xOffset */, 0.0f /* yOffset */);
            if (destination == WallpaperPersister.DEST_BOTH) {
                wallpaperManager.clear(WallpaperManager.FLAG_LOCK);
            }
            onWallpaperApplied(wallpaper, activity);
            if (callback != null) {
                callback.onSuccess(wallpaper);
            }
        } catch (RuntimeException | IOException e) {
            onWallpaperApplyError(e, activity);
            if (callback != null) {
                callback.onError(e);
            }
        }

    }

之后调用WallpaperPersister接口中的setIndividualWallpaper方法,具体实现类为DefaultWallpaperPersister

 @Override
    public 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() {
                @Override
                public 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() {
                @Override
                public 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() {
            @Override
            public void onBitmapCropped(Bitmap croppedBitmap) {
                setIndividualWallpaper(wallpaper, croppedBitmap, destination, callback);
            }

            @Override
            public void onError(@Nullable Throwable e) {
                callback.onError(e);
            }
        });
    }

接着调用不同参数的setIndividualWallpaper

/**
     * Sets a static individual wallpaper to the system via the WallpaperManager.
     *
     * @param wallpaper     Wallpaper model object.
     * @param croppedBitmap Bitmap representing the individual wallpaper image.
     * @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, Bitmap croppedBitmap,
            @Destination int destination, SetWallpaperCallback callback) {
        SetWallpaperTask setWallpaperTask =
                new SetWallpaperTask(wallpaper, croppedBitmap, destination, callback);
        setWallpaperTask.execute();
    }

继续追踪SetWallpaperTask,找到其中开启线程设置壁纸的位置

 @Override
        protected 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_BOTH
                whichWallpaper = WallpaperManagerCompat.FLAG_SYSTEM
                        | WallpaperManagerCompat.FLAG_LOCK;
            }


            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()) {
                    copyRotatingWallpaperToLock();
                }
                setImageWallpaperMetadata(mDestination, wallpaperId);
                return true;
            } else {
                return false;
            }
        }

之后调用setBitmapToWallpaperManagerCompat/setStreamToWallpaperManagerCompat方法设置壁纸

 private int setBitmapToWallpaperManagerCompat(Bitmap wallpaperBitmap, boolean allowBackup,
            int whichWallpaper) {
        ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
        if (wallpaperBitmap.compress(CompressFormat.JPEG, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
            try {
                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");
            try {
                return mWallpaperManagerCompat.setBitmap(
                        wallpaperBitmap,
                        null /* visibleCropHint */,
                        allowBackup,
                        whichWallpaper);
            } catch (IOException e) {
                Log.e(TAG, "unable to set wallpaper");
                return 0;
            }
        }
    }
    
    private int setStreamToWallpaperManagerCompat(InputStream inputStream, boolean allowBackup,
            int whichWallpaper) {
        try {
            return mWallpaperManagerCompat.setStream(inputStream, null, allowBackup,
                    whichWallpaper);
        } catch (IOException e) {
            return 0;
        }
    }

接着会调用mWallpaperManagerCompat.setBitmap/setStream方法,WallpaperManagerCompatVN : WallpaperManagerCompatV16 : WallpaperManagerCompat(继承关系),最终会调用WallpaperManager的setStream或setBitmap方法.所以追踪到/alps/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);
    }
    
    /**
     * Version of {@link #setStream(InputStream, Rect, boolean)} that allows the caller
     * to specify which of the supported wallpaper categories to set.
     *
     * @param bitmapData A stream containing the raw data to install as a wallpaper.  This
     *     data can be in any format handled by {@link BitmapRegionDecoder}.
     * @param visibleCropHint The rectangular subregion of the streamed image that should be
     *     displayed as wallpaper.  Passing {@code null} for this parameter means that
     *     the full image should be displayed if possible given the image's and device's
     *     aspect ratios, etc.
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *     image for restore to a future device; {@code false} otherwise.
     * @param which Flags indicating which wallpaper(s) to configure with the new imagery.
     * @return An integer ID assigned to the newly active wallpaper; or zero on failure.
     *
     * @see #getWallpaperId(int)
     * @see #FLAG_LOCK
     * @see #FLAG_SYSTEM
     *
     * @throws IOException
     */
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setStream(InputStream bitmapData, Rect visibleCropHint,
            boolean allowBackup, @SetWallpaperFlags int which)
                    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, mContext.getUserId());
            if (fd != null) {
                FileOutputStream fos = null;
                try {
                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                    copyStreamToWallpaperFile(bitmapData, fos);
                    fos.close();
                    completion.waitForCompletion();
                } finally {
                    IoUtils.closeQuietly(fos);
                }
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }

        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
    }

通过AIDL的方式绑定服务,使用setWallpaper方法设置壁纸,绑定的服务为WallpaperManagerService,从而找到/frameworks/base/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java

 public 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 image
        if (cropHint == null) {
            cropHint = new Rect(0, 0, 0, 0);
        } else {
            if (cropHint.width() < 0 || cropHint.height() < 0
                    || cropHint.left < 0
                    || cropHint.top < 0) {
                throw new IllegalArgumentException("Invalid crop rect supplied: " + cropHint);
            }
        }

        synchronized (mLock) {
            if (DEBUG) Slog.v(TAG, "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(TAG, "Migrating current wallpaper to be lock-only before"
                        + "updating system wallpaper");
                migrateSystemToLockWallpaperLocked(userId);
            }

            wallpaper = getWallpaperSafeLocked(userId, which);
            final long ident = Binder.clearCallingIdentity();
            try {
                ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
                if (pfd != null) {
                    wallpaper.imageWallpaperPending = true;
                    wallpaper.whichPending = which;
                    wallpaper.setComplete = completion;
                    wallpaper.cropHint.set(cropHint);
                    wallpaper.allowBackup = allowBackup;
                }
                return pfd;
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

追到头疼…就到这了 QWQ

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WallpaperPicker是一个在Android系统中设置壁纸的应用程序。在Android 10.0中,关于设置系统壁纸的是一个名为WallpaperPicker2的应用程序,其源码位于package/apps/目录下。 如果想要在WallpaperPicker2中添加动态壁纸服务,可以通过在AndroidManifest.xml文件中注册动态壁纸服务,并添加相应的intent-filter和meta-data。具体的注册代码如下所示: ``` <service android:name="com.android.wallpaper.widget.GIFWallpaperService" android:enabled="true" android:label="GifWallpaper" android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService" /> </intent-filter> <meta-data android:name="android.service.wallpaper" android:resource="@xml/livepaper"></meta-data> </service> ``` 这样,在更换壁纸时,就可以将动态壁纸作为系统默认的动态壁纸使用。 此外,还可以通过资源文件的方式来设置壁纸。例如,可以使用以下代码将指定的资源文件设置壁纸: ``` public void onSetWallpaperForBitmap(View view) { WallpaperManager wallpaperManager = WallpaperManager.getInstance(this); try { wallpaperManager.setResource(R.raw.wallpaper); } catch (IOException e) { e.printStackTrace(); } } ``` 这样就可以将指定的资源文件作为壁纸设置到系统中。 在Android 10.0的系统产品开发中,如果需要添加动态壁纸的功能,可以通过修改WallpaperPicker2应用程序来实现。具体可以参考位于packages\apps\WallpaperPicker2\src\com\android\wallpaper\widget\GIFWallpaperService.java的核心类来添加动态壁纸服务。此外,还可以对WallpaperPicker2应用程序进行定制化开发,以实现动态壁纸的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值