OSDN Git Service

394c196c9a6043817cb56e073ce3c3643d29f308
[android-x86/frameworks-base.git] / services / accessibility / java / com / android / server / accessibility / DisplayAdjustmentUtils.java
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.server.accessibility;
18
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.opengl.Matrix;
22 import android.os.IBinder;
23 import android.os.Parcel;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.provider.Settings;
27 import android.util.Slog;
28 import android.view.accessibility.AccessibilityManager;
29
30 /**
31  * Utility methods for performing accessibility display adjustments.
32  */
33 class DisplayAdjustmentUtils {
34     private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName();
35
36     /** Matrix and offset used for converting color to gray-scale. */
37     private static final float[] GRAYSCALE_MATRIX = new float[] {
38         .2126f, .2126f, .2126f, 0,
39         .7152f, .7152f, .7152f, 0,
40         .0722f, .0722f, .0722f, 0,
41              0,      0,      0, 1
42     };
43
44     /** Matrix and offset used for value-only display inversion. */
45     private static final float[] INVERSION_MATRIX_VALUE_ONLY = new float[] {
46            0, -.5f, -.5f, 0,
47         -.5f,    0, -.5f, 0,
48         -.5f, -.5f,    0, 0,
49            1,    1,    1, 1
50     };
51
52     /** Default inversion mode for display color correction. */
53     private static final int DEFAULT_DISPLAY_DALTONIZER =
54             AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY;
55
56     /**
57      * Returns whether the specified user with has any display color
58      * adjustments.
59      */
60     public static boolean hasAdjustments(Context context, int userId) {
61         final ContentResolver cr = context.getContentResolver();
62
63         boolean hasColorTransform = Settings.Secure.getIntForUser(
64                 cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1;
65
66         if (!hasColorTransform) {
67             hasColorTransform |= Settings.Secure.getIntForUser(
68                 cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) == 1;
69         }
70
71         return hasColorTransform;
72     }
73
74     /**
75      * Applies the specified user's display color adjustments.
76      */
77     public static void applyAdjustments(Context context, int userId) {
78         final ContentResolver cr = context.getContentResolver();
79         float[] colorMatrix = new float[16];
80         float[] outputMatrix = new float[16];
81         boolean hasColorTransform = false;
82
83         Matrix.setIdentityM(colorMatrix, 0);
84
85         final boolean inversionEnabled = Settings.Secure.getIntForUser(
86                 cr, Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) == 1;
87         if (inversionEnabled) {
88             final float[] inversionMatrix = INVERSION_MATRIX_VALUE_ONLY;
89             Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, inversionMatrix, 0);
90
91             colorMatrix = outputMatrix;
92             outputMatrix = colorMatrix;
93
94             hasColorTransform = true;
95         }
96
97         final boolean daltonizerEnabled = Settings.Secure.getIntForUser(
98                 cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0;
99         if (daltonizerEnabled) {
100             final int daltonizerMode = Settings.Secure.getIntForUser(cr,
101                     Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER,
102                     userId);
103             // Monochromacy isn't supported by the native Daltonizer.
104             if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
105                 Matrix.multiplyMM(outputMatrix, 0, colorMatrix, 0, GRAYSCALE_MATRIX, 0);
106
107                 final float[] temp = colorMatrix;
108                 colorMatrix = outputMatrix;
109                 outputMatrix = temp;
110
111                 hasColorTransform = true;
112                 nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
113             } else {
114                 nativeSetDaltonizerMode(daltonizerMode);
115             }
116         } else {
117             nativeSetDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
118         }
119
120         if (hasColorTransform) {
121             nativeSetColorTransform(colorMatrix);
122         } else {
123             nativeSetColorTransform(null);
124         }
125     }
126
127     /**
128      * Sets the surface flinger's Daltonization mode. This adjusts the color
129      * space to correct for or simulate various types of color blindness.
130      *
131      * @param mode new Daltonization mode
132      */
133     private static void nativeSetDaltonizerMode(int mode) {
134         try {
135             final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
136             if (flinger != null) {
137                 final Parcel data = Parcel.obtain();
138                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
139                 data.writeInt(mode);
140                 flinger.transact(1014, data, null, 0);
141                 data.recycle();
142             }
143         } catch (RemoteException ex) {
144             Slog.e(LOG_TAG, "Failed to set Daltonizer mode", ex);
145         }
146     }
147
148     /**
149      * Sets the surface flinger's color transformation as a 4x4 matrix. If the
150      * matrix is null, color transformations are disabled.
151      *
152      * @param m the float array that holds the transformation matrix, or null to
153      *            disable transformation
154      */
155     private static void nativeSetColorTransform(float[] m) {
156         try {
157             final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
158             if (flinger != null) {
159                 final Parcel data = Parcel.obtain();
160                 data.writeInterfaceToken("android.ui.ISurfaceComposer");
161                 if (m != null) {
162                     data.writeInt(1);
163                     for (int i = 0; i < 16; i++) {
164                         data.writeFloat(m[i]);
165                     }
166                 } else {
167                     data.writeInt(0);
168                 }
169                 flinger.transact(1015, data, null, 0);
170                 data.recycle();
171             }
172         } catch (RemoteException ex) {
173             Slog.e(LOG_TAG, "Failed to set color transform", ex);
174         }
175     }
176
177 }