赞
踩
平台: RK3568 + Android 11
在一些特殊的日子,如默哀日、灾难日,纪念日,哀悼日等,许多的APP、网页、海报等都开始使用黑白色主题。Android 的全局黑白实现方案,可以考虑使用模拟颜色空间的方法。
借助硬件加速渲染选项,您可以利用基于硬件的选项(如 GPU、硬件层和多重采样抗锯齿 (MSAA)针对目标硬件平台优化应用。
点按模拟颜色空间可以更改整个设备界面的配色方案。此设置下面的选项是指色盲类型。可选项如下:
其中“红色弱视”是指红绿色盲,红色弱视;“绿色弱视”(图 8 所示)是指红绿色盲,绿色弱视。
如果您在模拟颜色空间中截取屏幕截图,它们会正常显示,如同没有更改配色方案。
在设置的开发选项中可以找到: 设置 > 系统 > 开发者选项 > 模拟颜色空间,
文本来源
rk3568_a11$ grep -r "模拟颜色空间" frameworks/base/packages/SettingsLib/
frameworks/base/packages/SettingsLib/res/values-zh-rCN/strings.xml
<string name="simulate_color_space" msgid="1206503300335835151">"模拟颜色空间"</string>
<string name="daltonizer_mode_monochromacy" msgid="362060873835885014">"全色盲"</string>
<string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"绿色弱视(红绿不分)"</string>
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
rk3568_a11$ grep -r "simulate_color_space" packages/apps/Settings
packages/apps/Settings/tests/robotests/src/com/android/settings/development/SimulateColorSpacePreferenceControllerTest.java: mListValues = mContext.getResources().getStringArray(R.array.simulate_color_space_values);
packages/apps/Settings/src/com/android/settings/development/SimulateColorSpacePreferenceController.java: private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
packages/apps/Settings/res/xml/development_settings.xml: android:entries="@array/simulate_color_space_entries"
packages/apps/Settings/res/xml/development_settings.xml: android:entryValues="@array/simulate_color_space_values"
packages/apps/Settings/res/xml/development_settings.xml: android:key="simulate_color_space"
packages/apps/Settings/res/xml/development_settings.xml: android:title="@string/simulate_color_space" />
packages/apps/Settings/res/xml/development_settings.xml 开发者选项
<ListPreference
android:entries="@array/simulate_color_space_entries"
android:entryValues="@array/simulate_color_space_values"
android:key="simulate_color_space"
android:summary="%s"
android:title="@string/simulate_color_space" />
对应的模式的值
frameworks/base/packages/SettingsLib/res/values/arrays.xml
<!-- Display color space adjustment modes for developers --> <string-array name="simulate_color_space_entries" translatable="false"> <item>@string/daltonizer_mode_disabled</item> <item>@string/daltonizer_mode_monochromacy</item> <item>@string/daltonizer_mode_deuteranomaly</item> <item>@string/daltonizer_mode_protanomaly</item> <item>@string/daltonizer_mode_tritanomaly</item> </string-array> <!-- Values for display color space adjustment modes for developers --> <string-array name="simulate_color_space_values" translatable="false"> <item>-1</item> <item>0</item> <item>2</item> <item>1</item> <item>3</item> </string-array>
修改系统设置值, 主要是使能和模式
packages/apps/Settings/src/com/android/settings/development/SimulateColorSpacePreferenceController.java
private void writeSimulateColorSpace(Object value) {
final ContentResolver cr = mContext.getContentResolver();
final int newMode = Integer.parseInt(value.toString());
if (newMode < 0) {
Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
SETTING_VALUE_OFF);
} else {
Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
SETTING_VALUE_ON);
Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, newMode);
}
}
服务里监听设置项变化并执行响应
frameworks/base/services/core/java/com/android/server/display/color/ColorDisplayService.java
/** * Apply the accessibility daltonizer transform based on the settings value. */ private void onAccessibilityDaltonizerChanged() { if (mCurrentUser == UserHandle.USER_NULL) { return; } final int daltonizerMode = isAccessiblityDaltonizerEnabled() ? Secure.getIntForUser(getContext().getContentResolver(), Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY, mCurrentUser) : AccessibilityManager.DALTONIZER_DISABLED; final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) { // Monochromacy isn't supported by the native Daltonizer implementation; use grayscale. dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, MATRIX_GRAYSCALE); dtm.setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); } else { dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, null); dtm.setDaltonizerMode(daltonizerMode); } }
frameworks/base/services/core/java/com/android/server/display/color/DisplayTransformManager.java
private static final int SURFACE_FLINGER_TRANSACTION_DALTONIZER = 1014 /** * Sets and applies a current color transform matrix for a given level. * <p> * Note: all color transforms are first composed to a single matrix in ascending order based on * level before being applied to the display. * * @param level the level used to identify and compose the color transform (low -> high) * @param value the 4x4 color transform matrix (in column-major order), or {@code null} to * remove the color transform matrix associated with the provided level */ public void setColorMatrix(int level, float[] value) { if (value != null && value.length != 16) { throw new IllegalArgumentException("Expected length: 16 (4x4 matrix)" + ", actual length: " + value.length); } synchronized (mColorMatrix) { final float[] oldValue = mColorMatrix.get(level); if (!Arrays.equals(oldValue, value)) { if (value == null) { mColorMatrix.remove(level); } else if (oldValue == null) { mColorMatrix.put(level, Arrays.copyOf(value, value.length)); } else { System.arraycopy(value, 0, oldValue, 0, value.length); } // Update the current color transform. applyColorMatrix(computeColorMatrixLocked()); } } } /** * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate * various types of color blindness. * * @param mode the new Daltonization mode, or -1 to disable */ public void setDaltonizerMode(int mode) { synchronized (mDaltonizerModeLock) { if (mDaltonizerMode != mode) { mDaltonizerMode = mode; applyDaltonizerMode(mode); } } } /** * Propagates the provided Daltonization mode to the SurfaceFlinger. */ private static void applyDaltonizerMode(int mode) { final Parcel data = Parcel.obtain(); data.writeInterfaceToken("android.ui.ISurfaceComposer"); data.writeInt(mode); try { sFlinger.transact(SURFACE_FLINGER_TRANSACTION_DALTONIZER, data, null, 0); } catch (RemoteException ex) { Slog.e(TAG, "Failed to set Daltonizer mode", ex); } finally { data.recycle(); } }
传到SurfaceFlinger
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { //............ switch (code) { case 1014: { Mutex::Autolock _l(mStateLock); // daltonize n = data.readInt32(); switch (n % 10) { case 1: mDaltonizer.setType(ColorBlindnessType::Protanomaly); break; case 2: mDaltonizer.setType(ColorBlindnessType::Deuteranomaly); break; case 3: mDaltonizer.setType(ColorBlindnessType::Tritanomaly); break; default: mDaltonizer.setType(ColorBlindnessType::None); break; } if (n >= 10) { mDaltonizer.setMode(ColorBlindnessMode::Correction); } else { mDaltonizer.setMode(ColorBlindnessMode::Simulation); } updateColorMatrixLocked(); return NO_ERROR; } //........................
实现的原理与黑白色是一样的:
packages/apps/Settings/res/xml/accessibility_daltonizer_settings.xml
<PreferenceCategory android:title="@string/daltonizer_type" android:key="daltonizer_mode_category" > <com.android.settingslib.widget.RadioButtonPreference android:key="daltonizer_mode_deuteranomaly" android:persistent="false" android:summary="@string/daltonizer_mode_deuteranomaly_summary" android:title="@string/daltonizer_mode_deuteranomaly_title" /> <com.android.settingslib.widget.RadioButtonPreference android:key="daltonizer_mode_protanomaly" android:persistent="false" android:summary="@string/daltonizer_mode_protanomaly_summary" android:title="@string/daltonizer_mode_protanomaly_title" /> <com.android.settingslib.widget.RadioButtonPreference android:key="daltonizer_mode_tritanomaly" android:persistent="false" android:summary="@string/daltonizer_mode_tritanomaly_summary" android:title="@string/daltonizer_mode_tritanomaly_title" /> </PreferenceCategory>
packages/apps/Settings/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@Override
protected int getPreferenceScreenResId() {
return R.xml.accessibility_daltonizer_settings;
}
packages/apps/Settings/src/com/android/settings/accessibility/DaltonizerRadioButtonPreferenceController.java
private static final String TYPE = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER;
private void putSecureString(String name, String value) {
Settings.Secure.putString(mContentResolver, name, value);
}
private void handlePreferenceChange(String value) {
putSecureString(TYPE, value);
}
普通APP没有调用的权限, 两种调用方法:
final android.content.ContentResolver cr = context.getContentResolver();
final int newMode = on ? 0 : -1;
if (newMode < 0) {
android.provider.Settings.Secure.putInt(cr, "accessibility_display_daltonizer_enabled",
0);
} else {
android.provider.Settings.Secure.putInt(cr, "accessibility_display_daltonizer_enabled",
1);
//public static final String ACCESSIBILITY_DISPLAY_DALTONIZER =
// "accessibility_display_daltonizer";
android.provider.Settings.Secure.putInt(cr, "accessibility_display_daltonizer", newMode);
}
settings put secure accessibility_display_daltonizer_enabled 1
settings put secure accessibility_display_daltonizer 0
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。