Android global black and white - simulated color space

overview

平台: RK3568 + Android 11

insert image description here

     On some special days, such as days of silence, disaster days, anniversaries, mourning days, etc., many apps, web pages, posters, etc. have begun to use black and white themes. For Android's global black and white implementation, you can consider using the method of simulating the color space .

insert image description here

      With the hardware-accelerated rendering option, you can take advantage of hardware-based options such as GPU, hardware layers, and multi-sample anti-aliasing (MSAA) to optimize your application for the target hardware platform.

Tap Simulate Color Space to change the color scheme of the entire device interface. The options below this setting refer to the type of color blindness. The options are as follows:

  • Disabled (no simulated color scheme)
  • Achromatopsia (color scheme limited to black, white, and gray)
  • Deuteranomaly (affects the display of red and green)
  • Protomaly (affects the display of red and green)
  • Procyanomaly (affects the display of blue and yellow)

Among them, "promatomaly" refers to red-green color blindness, protanomaly; "deuteranomaly" (shown in Figure 8) refers to red-green color blindness, deuteranomaly.
If you take screenshots in the simulated color space, they will display normally as if the color scheme had not been changed.

accomplish

     It can be found in the development options of Settings: Settings > System > Developer Options > Simulation Color Space ,

text source

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 Developer Options

        <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" />

The value of the corresponding mode

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>

Modify system settings, mainly enable and mode

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);
        }
    }

Monitor changes in setting items in the service and execute responses

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();
        }
    }

Pass to 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;
            }
    //........................

About Settings > Color Correction

The principle of implementation is the same as black and white:
insert image description here

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);
    }

How to call the APP?

     Ordinary APP does not have the permission to call, there are two calling methods:

  1. App has system uid
		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);
        }
  1. The platform is ROOT, execute the command
settings put secure accessibility_display_daltonizer_enabled 1
settings put secure accessibility_display_daltonizer 0

reference

Android APP global black and white implementation scheme
Android global setting APP to black and white mode two solutions
Configure the developer options on the device

Guess you like

Origin blog.csdn.net/ansondroider/article/details/131112051