问题描述

Android13-EDLA 项目中,按照认证需求,需要验证 M56 - Monochrome App icon ,具体需求如下图,可通过 Wallpaper & Style 打开/关闭 Themed Icon功能。测试发现Wallpaper & Style中没有此项设置,无法开关 Themed Icon功能 。

原因分析:

因为项目中使用的是原生的壁纸(com.android.wallpaper),一开始怀疑是原生的壁纸没有Theme icon的功能设置,需要预置Google Wallpaper。

解决方案:

预置Google Wallpaper

1. partner_gms/apps/ 目录下添加GoogleWallpaper 目录

GoogleWallpaper.apk 可自行官网下载,Android.mk 内容如下

###############################################################################

# GoogleWallpaper

LOCAL_PATH := $(my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := GoogleWallpaper

LOCAL_MODULE_OWNER := google

LOCAL_MODULE_CLASS := APPS

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)

#LOCAL_PRIVILEGED_MODULE := true

LOCAL_CERTIFICATE := platform

LOCAL_SYSTEM_EXT_MODULE := true

LOCAL_SRC_FILES := $(LOCAL_MODULE).apk

LOCAL_USES_LIBRARIES := org.apache.http.legacy

LOCAL_OPTIONAL_USES_LIBRARIES := androidx.window.extensions androidx.window.sidecar

#LOCAL_OVERRIDES_PACKAGES :=

#LOCAL_REQUIRED_MODULES :=

include $(BUILD_PREBUILT)

LOCAL_SYSTEM_EXT_MODULE := true 预置到 system_ext 下,若没有设置此项,默认编译生成的apk会在system 分区。在system分区时需要额外添加权限白名单,不然会崩溃报错。

2. vendor/partner_gms/products/gms.mk 添加 DeskClockGoogle,添加后编包时才会编译DeskClockGoogle。

PRODUCT_PACKAGES += \

DeskClockGoogle \

3. 预置应用后还需要修改Launcher3 和Setting 的配置。

/device/xxx/common/products/tablet/overlay/packages/apps/Launcher3/res/values/config.xml

-- com.android.wallpaper

++ com.google.android.apps.wallpaper

将wallpaper_picker_package 配置成 com.google.android.apps.wallpaper。 Launcher3默认的配置文件位置在 packages/apps/Launcher3/res/values/config.xml ,因为存在overlay类,所以需要修改overlay类 才起作用。

device/xxx/common/products/tablet/overlay/packages/apps/Settings/res/values/config.xml

-- com.android.wallpaper

++ com.google.android.apps.wallpaper

将config_wallpaper_picker_package 设置为 com.google.android.apps.wallpaper,跟前面一起,需要修改overlay 类才起作用

4. 编译大包升级系统后,检查 Wallpaper & Style 界面是否是Google Wallpaper 的。

进入 Wallpaper & Style 界面 (Launcher3 或者Setting 进入), 串口执行指令: dumpsys window | grep “mCurrentFocus” 现在是 com.google.android.apps.wallpaper 则说明替换成功。

5. 替换成GoogleWallpaper 后发现,Wallpaper & Style 中 不显示 Wallpaper colors 。如下图所示,红框部分不显示。

查阅官方文档发现,GoogleWallpaper 显示 Wallpaper colors 需要满足两个条件。

frameworks/base/packages/SystemUI/res/values/flags.xml 中的 flag_monet 必须设置为true。必须安装 com.google.android.apps.customization.pixel 。

6.预置 com.google.android.apps.customization.pixel

预置方法跟 GoogleWallpaper 一致,参考修改即可。 Android.mk

###############################################################################

# GoogleWallpaper

LOCAL_PATH := $(my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := CustomizationPixel

LOCAL_MODULE_OWNER := google

LOCAL_MODULE_CLASS := APPS

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)

#LOCAL_PRIVILEGED_MODULE := true

LOCAL_CERTIFICATE := platform

LOCAL_SYSTEM_EXT_MODULE := true

LOCAL_SRC_FILES := $(LOCAL_MODULE).apk

#LOCAL_USES_LIBRARIES := org.apache.http.legacy

#LOCAL_OPTIONAL_USES_LIBRARIES := androidx.window.extensions androidx.window.sidecar

#LOCAL_OVERRIDES_PACKAGES :=

#LOCAL_REQUIRED_MODULES :=

include $(BUILD_PREBUILT)

vendor/partner_gms/products/gms.mk 添加 CustomizationPixel

PRODUCT_PACKAGES += \

CustomizationPixel\

整编大包后验证有效。

7. Theam icon 不显示的问题。

由于预置的GoogleWallpaper无源码,且没有相关的文档,我们可以从Android版wallpaper分析,ThemePicker(com.android.wallpaper)。

1. 从Theam icon 字符入手,ThemePicker 中检索 Theam icon.

Theam icon —>themed_icon_title(string.xml )–>themed_icon_section_view.xml(layout)—>ThemedIconSectionView.java -->ThemedIconSectionController.java

2. ThemedIconSectionController.java 中定义了 isAvailable方法,按字面意思就是获取 Themed Icon 是否可用。

...

@Override

public boolean isAvailable(@Nullable Context context) {

return context != null && mThemedIconOptionsProvider.isThemedIconAvailable();

}

...

3. ThemedIconSwitchProvider.java

...

/** Returns {@code true} if themed icon feature is available. 如果themed icon 功能可用返回true */

public boolean isThemedIconAvailable() {

return mThemedIconUtils.isThemedIconAvailable();

}

...

4. ThemedIconUtils.java (重点类)

private ProviderInfo mProviderInfo;

public ThemedIconUtils(Context context, String authorityMetaKey) {

mContext = context;

Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);

ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivity(homeIntent,

PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA);

if (resolveInfo != null && resolveInfo.activityInfo.metaData != null) {

mProviderAuthority = resolveInfo.activityInfo.metaData.getString(authorityMetaKey);

} else {

mProviderAuthority = null;

}

mProviderInfo = TextUtils.isEmpty(mProviderAuthority) ? null :

mContext.getPackageManager().resolveContentProvider(mProviderAuthority, 0);

if (mProviderInfo != null && !TextUtils.isEmpty(mProviderInfo.readPermission)) {

if (mContext.checkSelfPermission(mProviderInfo.readPermission)

!= PackageManager.PERMISSION_GRANTED) {

mProviderInfo = null;

}

}

}

...

/**

* Returns if themed icon is available.

*

* @return true if themed icon feature is available, false otherwise.

*/

boolean isThemedIconAvailable() {

return mProviderInfo != null;

}

...

Themed Icon 功能是否可用是 通过判断mProviderInfo是否为空,而 mProviderInfo 是在 ThemedIconUtils 构造方法中创建。在构造函数中获取满足 CATEGORY_HOME 、MATCH_DEFAULT_ONLY 、GET_META_DATA 的 的Activity组件(resolveInfo );并获取key为authorityMetaKey的值。

ThemedIconSwitchProvider.java

...

/** Returns the {@link ThemedIconSwitchProvider} instance. */

public static ThemedIconSwitchProvider getInstance(Context context) {

if (sThemedIconSwitchProvider == null) {

Context appContext = context.getApplicationContext();

sThemedIconSwitchProvider = new ThemedIconSwitchProvider(

appContext.getContentResolver(),

new ThemedIconUtils(appContext,

appContext.getString(R.string.themed_icon_metadata_key)),

(CustomizationPreferences) InjectorProvider.getInjector()

.getPreferences(appContext));

}

return sThemedIconSwitchProvider;

}

...

string.xml

com.android.launcher3.themedicon.option

6. 也就是说,Themed Icon 功能是否支持,由满足 CATEGORY_HOME 、MATCH_DEFAULT_ONLY 、GET_META_DATA 的 的Activity组件, 是否定义的了 key值为 com.android.launcher3.themedicon.option 的 metaData 标签。而满足这个要求的Activity就是Launcher3 的Home Activity 。满足要求的有两个Activity。

packages/apps/Launcher3/AndroidManifest.xml 的 com.android.launcher3.Launcher

android:name="com.android.launcher3.Launcher"

android:launchMode="singleTask"

android:clearTaskOnLaunch="true"

android:stateNotNeeded="true"

android:windowSoftInputMode="adjustPan"

android:screenOrientation="unspecified"

android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"

android:resizeableActivity="true"

android:resumeWhilePausing="true"

android:taskAffinity=""

android:exported="true"

android:enabled="true">

android:name="com.android.launcher3.grid.control"

android:value="${packageName}.grid_control" />

++

++ android:name="com.android.launcher3.themedicon.option"

++ android:value="${packageName}.grid_control" />

packages/apps/Launcher3/quickstep/AndroidManifest-launcher.xml 的 com.android.launcher3.uioverrides.QuickstepLauncher

android:name="com.android.launcher3.uioverrides.QuickstepLauncher"

android:launchMode="singleTask"

android:clearTaskOnLaunch="true"

android:stateNotNeeded="true"

android:windowSoftInputMode="adjustPan"

android:screenOrientation="unspecified"

android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"

android:resizeableActivity="true"

android:resumeWhilePausing="true"

android:taskAffinity=""

android:exported="true"

android:enabled="true">

android:name="com.android.launcher3.grid.control"

android:value="${packageName}.grid_control" />

++

++ android:name="com.android.launcher3.themedicon.option"

++ android:value="${packageName}.grid_control" />

编译验证发现Theme Icon 正常显示,且功能正常。

总结

-其实Theme icon不显示问题跟Google Wallpaper 无关,应该在 Launcher3 的HomeActivity 配置 meta-data 即可, 感兴趣的可以自行验证测试,如有纰漏或分析错误,欢迎指出。

参考

在 aosp 中启用 Material You design

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: