blob: 62e5c66612571732c32891c213d6f279c5f75039 [file] [log] [blame]
Steve Kondik5ee87cb2015-08-16 22:33:30 -07001/*
2 * Copyright (C) 2015 The CyanogenMod 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 */
16package cyanogenmod.hardware;
17
18import android.content.Context;
19import android.os.IBinder;
20import android.os.RemoteException;
21import android.os.ServiceManager;
22import android.util.Log;
23
24import cyanogenmod.app.CMContextConstants;
25
26import java.lang.IllegalArgumentException;
27import java.util.Arrays;
28import java.util.List;
29
30/**
31 * Manages access to CyanogenMod hardware extensions
32 *
33 * To get the instance of this class, utilize CMHardwareManager#getInstance(Context context)
34 *
35 */
36public final class CMHardwareManager {
37 private static final String TAG = "CMHardwareManager";
38
39 private static ICMHardwareService sService;
40
41 private Context mContext;
42 /**
43 * Adaptive backlight support (this refers to technologies like NVIDIA SmartDimmer,
44 * QCOM CABL or Samsung CABC)
45 */
46 public static final int FEATURE_ADAPTIVE_BACKLIGHT = 0x1;
47
48 /**
49 * Color enhancement support
50 */
51 public static final int FEATURE_COLOR_ENHANCEMENT = 0x2;
52
53 /**
54 * Display RGB color calibration
55 */
56 public static final int FEATURE_DISPLAY_COLOR_CALIBRATION = 0x4;
57
58 /**
59 * Display gamma calibration
60 */
61 public static final int FEATURE_DISPLAY_GAMMA_CALIBRATION = 0x8;
62
63 /**
64 * High touch sensitivity for touch panels
65 */
66 public static final int FEATURE_HIGH_TOUCH_SENSITIVITY = 0x10;
67
68 /**
69 * Hardware navigation key disablement
70 */
71 public static final int FEATURE_KEY_DISABLE = 0x20;
72
73 /**
74 * Long term orbits (LTO)
75 */
76 public static final int FEATURE_LONG_TERM_ORBITS = 0x40;
77
78 /**
79 * Serial number other than ro.serialno
80 */
81 public static final int FEATURE_SERIAL_NUMBER = 0x80;
82
83 /**
84 * Increased display readability in bright light
85 */
86 public static final int FEATURE_SUNLIGHT_ENHANCEMENT = 0x100;
87
88 /**
89 * Double-tap the touch panel to wake up the device
90 */
91 public static final int FEATURE_TAP_TO_WAKE = 0x200;
92
93 /**
94 * Variable vibrator intensity
95 */
96 public static final int FEATURE_VIBRATOR = 0x400;
97
98 /**
99 * Touchscreen hovering
100 */
101 public static final int FEATURE_TOUCH_HOVERING = 0x800;
102
103 private static final List<Integer> BOOLEAN_FEATURES = Arrays.asList(
104 FEATURE_ADAPTIVE_BACKLIGHT,
105 FEATURE_COLOR_ENHANCEMENT,
106 FEATURE_HIGH_TOUCH_SENSITIVITY,
107 FEATURE_KEY_DISABLE,
108 FEATURE_SUNLIGHT_ENHANCEMENT,
109 FEATURE_TAP_TO_WAKE,
110 FEATURE_TOUCH_HOVERING,
111 );
112
113 private static CMHardwareManager sCMHardwareManagerInstance;
114
115 /**
116 * @hide to prevent subclassing from outside of the framework
117 */
118 private CMHardwareManager(Context context) {
119 Context appContext = context.getApplicationContext();
120 if (appContext != null) {
121 mContext = appContext;
122 } else {
123 mContext = context;
124 }
125 sService = getService();
126 }
127
128 /**
129 * Get or create an instance of the {@link cyanogenmod.hardware.CMHardwareManager}
130 * @param context
131 * @return {@link CMHardwareManager}
132 */
133 public static CMHardwareManager getInstance(Context context) {
134 if (sCMHardwareManagerInstance == null) {
135 sCMHardwareManagerInstance = new CMHardwareManager(context);
136 }
137 return sCMHardwareManagerInstance;
138 }
139
140 /** @hide */
141 private static ICMHardwareService getService() {
142 if (sService != null) {
143 return sService;
144 }
145 IBinder b = ServiceManager.getService(CMContextConstants.CM_HARDWARE_SERVICE);
146 if (b != null) {
147 sService = ICMHardwareService.Stub.asInterface(b);
148 return sService;
149 }
150 return null;
151 }
152
153 /**
154 * @return the supported features bitmask
155 */
156 public int getSupportedFeatures() {
157 try {
158 return getService().getSupportedFeatures();
159 } catch (RemoteException e) {
160 }
161 return 0;
162 }
163
164 /**
165 * Determine if a CM Hardware feature is supported on this device
166 *
167 * @param feature The CM Hardware feature to query
168 *
169 * @return true if the feature is supported, false otherwise.
170 */
171 public boolean isSupported(int feature) {
172 return feature == (getSupportedFeatures() & feature);
173 }
174
175 /**
176 * Determine if the given feature is enabled or disabled.
177 *
178 * Only used for features which have simple enable/disable controls.
179 *
180 * @param feature the CM Hardware feature to query
181 *
182 * @return true if the feature is enabled, false otherwise.
183 */
184 public boolean get(int feature) {
185 if (!BOOLEAN_FEATURES.contains(feature)) {
186 throw new IllegalArgumentException(feature + " is not a boolean");
187 }
188
189 try {
190 return getService().get(feature);
191 } catch (RemoteException e) {
192 }
193 return false;
194 }
195
196 /**
197 * Enable or disable the given feature
198 *
199 * Only used for features which have simple enable/disable controls.
200 *
201 * @param feature the CM Hardware feature to set
202 * @param enable true to enable, false to disale
203 *
204 * @return true if the feature is enabled, false otherwise.
205 */
206 public boolean set(int feature, boolean enable) {
207 if (!BOOLEAN_FEATURES.contains(feature)) {
208 throw new IllegalArgumentException(feature + " is not a boolean");
209 }
210
211 try {
212 return getService().set(feature, enable);
213 } catch (RemoteException e) {
214 }
215 return false;
216 }
217
218 private int getArrayValue(int[] arr, int idx, int defaultValue) {
219 if (arr == null || arr.length <= idx) {
220 return defaultValue;
221 }
222
223 return arr[idx];
224 }
225
226 /**
227 * {@hide}
228 */
229 public static final int VIBRATOR_INTENSITY_INDEX = 0;
230 /**
231 * {@hide}
232 */
233 public static final int VIBRATOR_DEFAULT_INDEX = 1;
234 /**
235 * {@hide}
236 */
237 public static final int VIBRATOR_MIN_INDEX = 2;
238 /**
239 * {@hide}
240 */
241 public static final int VIBRATOR_MAX_INDEX = 3;
242 /**
243 * {@hide}
244 */
245 public static final int VIBRATOR_WARNING_INDEX = 4;
246
247 private int[] getVibratorIntensityArray() {
248 try {
249 return getService().getVibratorIntensity();
250 } catch (RemoteException e) {
251 }
252 return null;
253 }
254
255 /**
256 * @return The current vibrator intensity.
257 */
258 public int getVibratorIntensity() {
259 return getArrayValue(getVibratorIntensityArray(), VIBRATOR_INTENSITY_INDEX, 0);
260 }
261
262 /**
263 * @return The default vibrator intensity.
264 */
265 public int getVibratorDefaultIntensity() {
266 return getArrayValue(getVibratorIntensityArray(), VIBRATOR_DEFAULT_INDEX, 0);
267 }
268
269 /**
270 * @return The minimum vibrator intensity.
271 */
272 public int getVibratorMinIntensity() {
273 return getArrayValue(getVibratorIntensityArray(), VIBRATOR_MIN_INDEX, 0);
274 }
275
276 /**
277 * @return The maximum vibrator intensity.
278 */
279 public int getVibratorMaxIntensity() {
280 return getArrayValue(getVibratorIntensityArray(), VIBRATOR_MAX_INDEX, 0);
281 }
282
283 /**
284 * @return The warning threshold vibrator intensity.
285 */
286 public int getVibratorWarningIntensity() {
287 return getArrayValue(getVibratorIntensityArray(), VIBRATOR_WARNING_INDEX, 0);
288 }
289
290 /**
291 * Set the current vibrator intensity
292 *
293 * @param intensity the intensity to set, between {@link #getVibratorMinIntensity()} and
294 * {@link #getVibratorMaxIntensity()} inclusive.
295 *
296 * @return true on success, false otherwise.
297 */
298 public boolean setVibratorIntensity(int intensity) {
299 try {
300 return getService().setVibratorIntensity(intensity);
301 } catch (RemoteException e) {
302 }
303 return false;
304 }
305
306 /**
307 * {@hide}
308 */
309 public static final int COLOR_CALIBRATION_RED_INDEX = 0;
310 /**
311 * {@hide}
312 */
313 public static final int COLOR_CALIBRATION_GREEN_INDEX = 1;
314 /**
315 * {@hide}
316 */
317 public static final int COLOR_CALIBRATION_BLUE_INDEX = 2;
318 /**
319 * {@hide}
320 */
321 public static final int COLOR_CALIBRATION_DEFAULT_INDEX = 3;
322 /**
323 * {@hide}
324 */
325 public static final int COLOR_CALIBRATION_MIN_INDEX = 4;
326 /**
327 * {@hide}
328 */
329 public static final int COLOR_CALIBRATION_MAX_INDEX = 5;
330
331 private int[] getDisplayColorCalibrationArray() {
332 try {
333 return getService().getDisplayColorCalibration();
334 } catch (RemoteException e) {
335 }
336 return null;
337 }
338
339 /**
340 * @return the current RGB calibration, where int[0] = R, int[1] = G, int[2] = B.
341 */
342 public int[] getDisplayColorCalibration() {
343 int[] arr = getDisplayColorCalibrationArray();
344 if (arr == null || arr.length < 3) {
345 return null;
346 }
347 return Arrays.copyOf(arr, 3);
348 }
349
350 /**
351 * @return the default value for all colors
352 */
353 public int getDisplayColorCalibrationDefault() {
354 return getArrayValue(getDisplayColorCalibrationArray(), COLOR_CALIBRATION_DEFAULT_INDEX, 0);
355 }
356
357 /**
358 * @return The minimum value for all colors
359 */
360 public int getDisplayColorCalibrationMin() {
361 return getArrayValue(getDisplayColorCalibrationArray(), COLOR_CALIBRATION_MIN_INDEX, 0);
362 }
363
364 /**
365 * @return The minimum value for all colors
366 */
367 public int getDisplayColorCalibrationMax() {
368 return getArrayValue(getDisplayColorCalibrationArray(), COLOR_CALIBRATION_MAX_INDEX, 0);
369 }
370
371 /**
372 * Set the display color calibration to the given rgb triplet
373 *
374 * @param rgb RGB color calibration. Each value must be between
375 * {@link getDisplayColorCalibrationMin()} and {@link getDisplayColorCalibrationMax()},
376 * inclusive.
377 *
378 * @return true on success, false otherwise.
379 */
380 public boolean setDisplayColorCalibration(int[] rgb) {
381 try {
382 return getService().setDisplayColorCalibration(rgb);
383 } catch (RemoteException e) {
384 }
385 return false;
386 }
387
388 /**
389 * {@hide}
390 */
391 public static final int GAMMA_CALIBRATION_RED_INDEX = 0;
392 /**
393 * {@hide}
394 */
395 public static final int GAMMA_CALIBRATION_GREEN_INDEX = 1;
396 /**
397 * {@hide}
398 */
399 public static final int GAMMA_CALIBRATION_BLUE_INDEX = 2;
400 /**
401 * {@hide}
402 */
403 public static final int GAMMA_CALIBRATION_MIN_INDEX = 3;
404 /**
405 * {@hide}
406 */
407 public static final int GAMMA_CALIBRATION_MAX_INDEX = 4;
408
409 private int[] getDisplayGammaCalibrationArray(int idx) {
410 try {
411 return getService().getDisplayGammaCalibration(idx);
412 } catch (RemoteException e) {
413 }
414 return null;
415 }
416
417 /**
418 * @return the number of RGB controls the device supports
419 */
420 public int getNumGammaControls() {
421 try {
422 return getService().getNumGammaControls();
423 } catch (RemoteException e) {
424 }
425 return 0;
426 }
427
428 /**
429 * @param the control to query
430 *
431 * @return the current RGB gamma calibration for the given control
432 */
433 public int[] getDisplayGammaCalibration(int idx) {
434 int[] arr = getDisplayGammaCalibrationArray(idx);
435 if (arr == null || arr.length < 3) {
436 return null;
437 }
438 return Arrays.copyOf(arr, 3);
439 }
440
441 /**
442 * @return the minimum value for all colors
443 */
444 public int getDisplayGammaCalibrationMin() {
445 return getArrayValue(getDisplayGammaCalibrationArray(0), GAMMA_CALIBRATION_MIN_INDEX, 0);
446 }
447
448 /**
449 * @return the maximum value for all colors
450 */
451 public int getDisplayGammaCalibrationMax() {
452 return getArrayValue(getDisplayGammaCalibrationArray(0), GAMMA_CALIBRATION_MAX_INDEX, 0);
453 }
454
455 /**
456 * Set the display gamma calibration for a specific control
457 *
458 * @param idx the control to set
459 * @param rgb RGB color calibration. Each value must be between
460 * {@link getDisplayGammaCalibrationMin()} and {@link getDisplayGammaCalibrationMax()},
461 * inclusive.
462 *
463 * @return true on success, false otherwise.
464 */
465 public boolean setDisplayGammaCalibration(int idx, int[] rgb) {
466 try {
467 return getService().setDisplayGammaCalibration(idx, rgb);
468 } catch (RemoteException e) {
469 }
470 return false;
471 }
472
473 /**
474 * @return the source location of LTO data, or null on failure
475 */
476 public String getLtoSource() {
477 try {
478 return getService().getLtoSource();
479 } catch (RemoteException e) {
480 }
481 return null;
482 }
483
484 /**
485 * @return the destination location of LTO data, or null on failure
486 */
487 public String getLtoDestination() {
488 try {
489 return getService().getLtoDestination();
490 } catch (RemoteException e) {
491 }
492 return null;
493 }
494
495 /**
496 * @return the interval, in milliseconds, to trigger LTO data download
497 */
498 public long getLtoDownloadInterval() {
499 try {
500 return getService().getLtoDownloadInterval();
501 } catch (RemoteException e) {
502 }
503 return 0;
504 }
505
506 /**
507 * @return the serial number to display instead of ro.serialno, or null on failure
508 */
509 public String getSerialNumber() {
510 try {
511 return getService().getSerialNumber();
512 } catch (RemoteException e) {
513 }
514 return null;
515 }
516
517 /**
518 * @return true if adaptive backlight should be enabled when sunlight enhancement
519 * is enabled.
520 */
521 public boolean requireAdaptiveBacklightForSunlightEnhancement() {
522 try {
523 return getService().requireAdaptiveBacklightForSunlightEnhancement();
524 } catch (RemoteException e) {
525 }
526 return false;
527 }
528}