diff --git a/Android.mk b/Android.mk index bac2019..b224af8 100644 --- a/Android.mk +++ b/Android.mk @@ -35,7 +35,8 @@ LOCAL_MODULE := org.cyanogenmod.platform LOCAL_MODULE_TAGS := optional LOCAL_JAVA_LIBRARIES := \ - services + services \ + org.cyanogenmod.hardware LOCAL_SRC_FILES := \ $(call all-java-files-under, $(cyanogenmod_src)) \ @@ -155,7 +156,7 @@ LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:= build/tools/droiddoc/templates-sdk LOCAL_DROIDDOC_OPTIONS:= \ -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/cmsdk_stubs_current_intermediates/src \ - -stubpackages cyanogenmod.alarmclock:cyanogenmod.app:cyanogenmod.os:cyanogenmod.profiles:cyanogenmod.platform:org.cyanogenmod.platform \ + -stubpackages cyanogenmod.alarmclock:cyanogenmod.app:cyanogenmod.hardware:cyanogenmod.os:cyanogenmod.profiles:cyanogenmod.platform:org.cyanogenmod.platform \ -api $(INTERNAL_CM_PLATFORM_API_FILE) \ -removedApi $(INTERNAL_CM_PLATFORM_REMOVED_API_FILE) \ -nodocs \ @@ -184,7 +185,7 @@ LOCAL_MODULE := cm-system-api-stubs LOCAL_DROIDDOC_OPTIONS:=\ -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/cmsdk_system_stubs_current_intermediates/src \ - -stubpackages cyanogenmod.alarmclock:cyanogenmod.app:cyanogenmod.os:cyanogenmod.profiles:cyanogenmod.platform:org.cyanogenmod.platform \ + -stubpackages cyanogenmod.alarmclock:cyanogenmod.app:cyanogenmod.hardware:cyanogenmod.os:cyanogenmod.profiles:cyanogenmod.platform:org.cyanogenmod.platform \ -showAnnotation android.annotation.SystemApi \ -api $(INTERNAL_CM_PLATFORM_SYSTEM_API_FILE) \ -removedApi $(INTERNAL_CM_PLATFORM_SYSTEM_REMOVED_API_FILE) \ diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/CMHardwareService.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/CMHardwareService.java new file mode 100644 index 0000000..9b880ef --- /dev/null +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/CMHardwareService.java @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.cyanogenmod.platform.internal; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.util.Log; + +import com.android.server.SystemService; + +import cyanogenmod.app.CMContextConstants; +import cyanogenmod.hardware.ICMHardwareService; +import cyanogenmod.hardware.CMHardwareManager; + +import java.io.File; + +import org.cyanogenmod.hardware.AdaptiveBacklight; +import org.cyanogenmod.hardware.ColorEnhancement; +import org.cyanogenmod.hardware.DisplayColorCalibration; +import org.cyanogenmod.hardware.DisplayGammaCalibration; +import org.cyanogenmod.hardware.HighTouchSensitivity; +import org.cyanogenmod.hardware.KeyDisabler; +import org.cyanogenmod.hardware.LongTermOrbits; +import org.cyanogenmod.hardware.SerialNumber; +import org.cyanogenmod.hardware.SunlightEnhancement; +import org.cyanogenmod.hardware.TapToWake; +import org.cyanogenmod.hardware.TouchscreenHovering; +import org.cyanogenmod.hardware.VibratorHW; + +public class CMHardwareService extends SystemService { + + private static final boolean DEBUG = true; + private static final String TAG = CMHardwareService.class.getSimpleName(); + + private final Context mContext; + private final CMHardwareInterface mCmHwImpl; + + private interface CMHardwareInterface { + public int getSupportedFeatures(); + public boolean get(int feature); + public boolean set(int feature, boolean enable); + + public int[] getDisplayColorCalibration(); + public boolean setDisplayColorCalibration(int[] rgb); + + public int getNumGammaControls(); + public int[] getDisplayGammaCalibration(int idx); + public boolean setDisplayGammaCalibration(int idx, int[] rgb); + + public int[] getVibratorIntensity(); + public boolean setVibratorIntensity(int intensity); + + public String getLtoSource(); + public String getLtoDestination(); + public long getLtoDownloadInterval(); + + public String getSerialNumber(); + + public boolean requireAdaptiveBacklightForSunlightEnhancement(); + } + + private class LegacyCMHardware implements CMHardwareInterface { + + private int mSupportedFeatures = 0; + + public LegacyCMHardware() { + if (AdaptiveBacklight.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT; + if (ColorEnhancement.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_COLOR_ENHANCEMENT; + if (DisplayColorCalibration.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION; + if (DisplayGammaCalibration.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION; + if (HighTouchSensitivity.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY; + if (KeyDisabler.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_KEY_DISABLE; + if (LongTermOrbits.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_LONG_TERM_ORBITS; + if (SerialNumber.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_SERIAL_NUMBER; + if (SunlightEnhancement.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT; + if (TapToWake.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_TAP_TO_WAKE; + if (VibratorHW.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_VIBRATOR; + if (TouchscreenHovering.isSupported()) + mSupportedFeatures |= CMHardwareManager.FEATURE_TOUCH_HOVERING; + } + + public int getSupportedFeatures() { + return mSupportedFeatures; + } + + public boolean get(int feature) { + switch(feature) { + case CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT: + return AdaptiveBacklight.isEnabled(); + case CMHardwareManager.FEATURE_COLOR_ENHANCEMENT: + return ColorEnhancement.isEnabled(); + case CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY: + return HighTouchSensitivity.isEnabled(); + case CMHardwareManager.FEATURE_KEY_DISABLE: + return KeyDisabler.isActive(); + case CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT: + return SunlightEnhancement.isEnabled(); + case CMHardwareManager.FEATURE_TAP_TO_WAKE: + return TapToWake.isEnabled(); + case CMHardwareManager.FEATURE_TOUCH_HOVERING: + return TouchscreenHovering.isEnabled(); + default: + Log.e(TAG, "feature " + feature + " is not a boolean feature"); + return false; + } + } + + public boolean set(int feature, boolean enable) { + switch(feature) { + case CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT: + return AdaptiveBacklight.setEnabled(enable); + case CMHardwareManager.FEATURE_COLOR_ENHANCEMENT: + return ColorEnhancement.setEnabled(enable); + case CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY: + return HighTouchSensitivity.setEnabled(enable); + case CMHardwareManager.FEATURE_KEY_DISABLE: + return KeyDisabler.setActive(enable); + case CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT: + return SunlightEnhancement.setEnabled(enable); + case CMHardwareManager.FEATURE_TAP_TO_WAKE: + return TapToWake.setEnabled(enable); + case CMHardwareManager.FEATURE_TOUCH_HOVERING: + return TouchscreenHovering.setEnabled(enable); + default: + Log.e(TAG, "feature " + feature + " is not a boolean feature"); + return false; + } + } + + private int[] splitStringToInt(String input, String delimiter) { + if (input == null || delimiter == null) { + return null; + } + String strArray[] = input.split(delimiter); + try { + int intArray[] = new int[strArray.length]; + for(int i = 0; i < strArray.length; i++) { + intArray[i] = Integer.parseInt(strArray[i]); + } + return intArray; + } catch (NumberFormatException e) { + /* ignore */ + } + return null; + } + + private String rgbToString(int[] rgb) { + StringBuilder builder = new StringBuilder(); + builder.append(rgb[CMHardwareManager.COLOR_CALIBRATION_RED_INDEX]); + builder.append(" "); + builder.append(rgb[CMHardwareManager.COLOR_CALIBRATION_GREEN_INDEX]); + builder.append(" "); + builder.append(rgb[CMHardwareManager.COLOR_CALIBRATION_BLUE_INDEX]); + return builder.toString(); + } + + public int[] getDisplayColorCalibration() { + int[] rgb = splitStringToInt(DisplayColorCalibration.getCurColors(), " "); + if (rgb == null || rgb.length != 3) { + Log.e(TAG, "Invalid color calibration string"); + return null; + } + int[] currentCalibration = new int[6]; + currentCalibration[CMHardwareManager.COLOR_CALIBRATION_RED_INDEX] = rgb[0]; + currentCalibration[CMHardwareManager.COLOR_CALIBRATION_GREEN_INDEX] = rgb[1]; + currentCalibration[CMHardwareManager.COLOR_CALIBRATION_BLUE_INDEX] = rgb[2]; + currentCalibration[CMHardwareManager.COLOR_CALIBRATION_DEFAULT_INDEX] = + DisplayColorCalibration.getDefValue(); + currentCalibration[CMHardwareManager.COLOR_CALIBRATION_MIN_INDEX] = + DisplayColorCalibration.getMinValue(); + currentCalibration[CMHardwareManager.COLOR_CALIBRATION_MAX_INDEX] = + DisplayColorCalibration.getMaxValue(); + return currentCalibration; + } + + public boolean setDisplayColorCalibration(int[] rgb) { + return DisplayColorCalibration.setColors(rgbToString(rgb)); + } + + public int getNumGammaControls() { + return DisplayGammaCalibration.getNumberOfControls(); + } + + public int[] getDisplayGammaCalibration(int idx) { + int[] rgb = splitStringToInt(DisplayGammaCalibration.getCurGamma(idx), " "); + if (rgb == null || rgb.length != 3) { + Log.e(TAG, "Invalid gamma calibration string"); + return null; + } + int[] currentCalibration = new int[5]; + currentCalibration[CMHardwareManager.GAMMA_CALIBRATION_RED_INDEX] = rgb[0]; + currentCalibration[CMHardwareManager.GAMMA_CALIBRATION_GREEN_INDEX] = rgb[1]; + currentCalibration[CMHardwareManager.GAMMA_CALIBRATION_BLUE_INDEX] = rgb[2]; + currentCalibration[CMHardwareManager.GAMMA_CALIBRATION_MIN_INDEX] = + DisplayGammaCalibration.getMinValue(idx); + currentCalibration[CMHardwareManager.GAMMA_CALIBRATION_MAX_INDEX] = + DisplayGammaCalibration.getMaxValue(idx); + return currentCalibration; + } + + public boolean setDisplayGammaCalibration(int idx, int[] rgb) { + return DisplayGammaCalibration.setGamma(idx, rgbToString(rgb)); + } + + public int[] getVibratorIntensity() { + int[] vibrator = new int[5]; + vibrator[CMHardwareManager.VIBRATOR_INTENSITY_INDEX] = VibratorHW.getCurIntensity(); + vibrator[CMHardwareManager.VIBRATOR_DEFAULT_INDEX] = VibratorHW.getDefaultIntensity(); + vibrator[CMHardwareManager.VIBRATOR_MIN_INDEX] = VibratorHW.getMinIntensity(); + vibrator[CMHardwareManager.VIBRATOR_MAX_INDEX] = VibratorHW.getMaxIntensity(); + vibrator[CMHardwareManager.VIBRATOR_WARNING_INDEX] = VibratorHW.getWarningThreshold(); + return vibrator; + } + + public boolean setVibratorIntensity(int intensity) { + return VibratorHW.setIntensity(intensity); + } + + public String getLtoSource() { + return LongTermOrbits.getSourceLocation(); + } + + public String getLtoDestination() { + File file = LongTermOrbits.getDestinationLocation(); + return file.getAbsolutePath(); + } + + public long getLtoDownloadInterval() { + return LongTermOrbits.getDownloadInterval(); + } + + public String getSerialNumber() { + return SerialNumber.getSerialNumber(); + } + + public boolean requireAdaptiveBacklightForSunlightEnhancement() { + return SunlightEnhancement.isAdaptiveBacklightRequired(); + } + } + + private CMHardwareInterface getImpl(Context context) { + return new LegacyCMHardware(); + } + + public CMHardwareService(Context context) { + super(context); + mContext = context; + mCmHwImpl = getImpl(context); + publishBinderService(CMContextConstants.CM_HARDWARE_SERVICE, mService); + } + + @Override + public void onStart() { + } + + private final IBinder mService = new ICMHardwareService.Stub() { + + private boolean isSupported(int feature) { + return (getSupportedFeatures() & feature) == feature; + } + + @Override + public int getSupportedFeatures() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + return mCmHwImpl.getSupportedFeatures(); + } + + @Override + public boolean get(int feature) { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(feature)) { + Log.e(TAG, "feature " + feature + " is not supported"); + return false; + } + return mCmHwImpl.get(feature); + } + + @Override + public boolean set(int feature, boolean enable) { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(feature)) { + Log.e(TAG, "feature " + feature + " is not supported"); + return false; + } + return mCmHwImpl.set(feature, enable); + } + + @Override + public int[] getDisplayColorCalibration() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION)) { + Log.e(TAG, "Display color calibration is not supported"); + return null; + } + return mCmHwImpl.getDisplayColorCalibration(); + } + + @Override + public boolean setDisplayColorCalibration(int[] rgb) { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION)) { + Log.e(TAG, "Display color calibration is not supported"); + return false; + } + if (rgb.length < 3) { + Log.e(TAG, "Invalid color calibration"); + return false; + } + return mCmHwImpl.setDisplayColorCalibration(rgb); + } + + @Override + public int getNumGammaControls() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { + Log.e(TAG, "Display gamma calibration is not supported"); + return 0; + } + return mCmHwImpl.getNumGammaControls(); + } + + @Override + public int[] getDisplayGammaCalibration(int idx) { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { + Log.e(TAG, "Display gamma calibration is not supported"); + return null; + } + return mCmHwImpl.getDisplayGammaCalibration(idx); + } + + @Override + public boolean setDisplayGammaCalibration(int idx, int[] rgb) { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { + Log.e(TAG, "Display gamma calibration is not supported"); + return false; + } + return mCmHwImpl.setDisplayGammaCalibration(idx, rgb); + } + + @Override + public int[] getVibratorIntensity() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_VIBRATOR)) { + Log.e(TAG, "Vibrator is not supported"); + return null; + } + return mCmHwImpl.getVibratorIntensity(); + } + + @Override + public boolean setVibratorIntensity(int intensity) { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_VIBRATOR)) { + Log.e(TAG, "Vibrator is not supported"); + return false; + } + return mCmHwImpl.setVibratorIntensity(intensity); + } + + @Override + public String getLtoSource() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_LONG_TERM_ORBITS)) { + Log.e(TAG, "Long term orbits is not supported"); + return null; + } + return mCmHwImpl.getLtoSource(); + } + + @Override + public String getLtoDestination() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_LONG_TERM_ORBITS)) { + Log.e(TAG, "Long term orbits is not supported"); + return null; + } + return mCmHwImpl.getLtoDestination(); + } + + @Override + public long getLtoDownloadInterval() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_LONG_TERM_ORBITS)) { + Log.e(TAG, "Long term orbits is not supported"); + return 0; + } + return mCmHwImpl.getLtoDownloadInterval(); + } + + @Override + public String getSerialNumber() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_SERIAL_NUMBER)) { + Log.e(TAG, "Serial number is not supported"); + return null; + } + return mCmHwImpl.getSerialNumber(); + } + + @Override + public boolean requireAdaptiveBacklightForSunlightEnhancement() { + mContext.enforceCallingOrSelfPermission( + cyanogenmod.platform.Manifest.permission.HARDWARE_ABSTRACTION_ACCESS, null); + if (!isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT)) { + Log.e(TAG, "Sunlight enhancement is not supported"); + return false; + } + return mCmHwImpl.requireAdaptiveBacklightForSunlightEnhancement(); + } + }; +} diff --git a/cm/res/AndroidManifest.xml b/cm/res/AndroidManifest.xml index 0891d7f..e664f54 100644 --- a/cm/res/AndroidManifest.xml +++ b/cm/res/AndroidManifest.xml @@ -63,6 +63,12 @@ android:icon="@drawable/ic_launcher_cyanogenmod" android:protectionLevel="normal" /> + + + modify the phone state and data connection with support to multiple SIMs Allows an app to modify the phone state and data connection with support to multiple SIMs. + + use hardware framework + Allows an app access to the CM hardware framework. + + Custom tile listener @@ -59,4 +64,5 @@ Other + diff --git a/src/java/cyanogenmod/app/CMContextConstants.java b/src/java/cyanogenmod/app/CMContextConstants.java index e4c6578..b79063a 100644 --- a/src/java/cyanogenmod/app/CMContextConstants.java +++ b/src/java/cyanogenmod/app/CMContextConstants.java @@ -73,4 +73,16 @@ public final class CMContextConstants { * @hide */ public static final String CM_TELEPHONY_MANAGER_SERVICE = "cmtelephonymanager"; + + /** + * Use with {@link android.content.Context#getSystemService} to retrieve a + * {@link cyanogenmod.hardware.CMHardwareManager} to manage the extended + * hardware features of the device. + * + * @see android.content.Context#getSystemService + * @see cyanogenmod.hardware.CMHardwareManager + * + * @hide + */ + public static final String CM_HARDWARE_SERVICE = "cmhardware"; } diff --git a/src/java/cyanogenmod/hardware/CMHardwareManager.java b/src/java/cyanogenmod/hardware/CMHardwareManager.java new file mode 100644 index 0000000..62e5c66 --- /dev/null +++ b/src/java/cyanogenmod/hardware/CMHardwareManager.java @@ -0,0 +1,528 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cyanogenmod.hardware; + +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +import cyanogenmod.app.CMContextConstants; + +import java.lang.IllegalArgumentException; +import java.util.Arrays; +import java.util.List; + +/** + * Manages access to CyanogenMod hardware extensions + * + * To get the instance of this class, utilize CMHardwareManager#getInstance(Context context) + * + */ +public final class CMHardwareManager { + private static final String TAG = "CMHardwareManager"; + + private static ICMHardwareService sService; + + private Context mContext; + /** + * Adaptive backlight support (this refers to technologies like NVIDIA SmartDimmer, + * QCOM CABL or Samsung CABC) + */ + public static final int FEATURE_ADAPTIVE_BACKLIGHT = 0x1; + + /** + * Color enhancement support + */ + public static final int FEATURE_COLOR_ENHANCEMENT = 0x2; + + /** + * Display RGB color calibration + */ + public static final int FEATURE_DISPLAY_COLOR_CALIBRATION = 0x4; + + /** + * Display gamma calibration + */ + public static final int FEATURE_DISPLAY_GAMMA_CALIBRATION = 0x8; + + /** + * High touch sensitivity for touch panels + */ + public static final int FEATURE_HIGH_TOUCH_SENSITIVITY = 0x10; + + /** + * Hardware navigation key disablement + */ + public static final int FEATURE_KEY_DISABLE = 0x20; + + /** + * Long term orbits (LTO) + */ + public static final int FEATURE_LONG_TERM_ORBITS = 0x40; + + /** + * Serial number other than ro.serialno + */ + public static final int FEATURE_SERIAL_NUMBER = 0x80; + + /** + * Increased display readability in bright light + */ + public static final int FEATURE_SUNLIGHT_ENHANCEMENT = 0x100; + + /** + * Double-tap the touch panel to wake up the device + */ + public static final int FEATURE_TAP_TO_WAKE = 0x200; + + /** + * Variable vibrator intensity + */ + public static final int FEATURE_VIBRATOR = 0x400; + + /** + * Touchscreen hovering + */ + public static final int FEATURE_TOUCH_HOVERING = 0x800; + + private static final List BOOLEAN_FEATURES = Arrays.asList( + FEATURE_ADAPTIVE_BACKLIGHT, + FEATURE_COLOR_ENHANCEMENT, + FEATURE_HIGH_TOUCH_SENSITIVITY, + FEATURE_KEY_DISABLE, + FEATURE_SUNLIGHT_ENHANCEMENT, + FEATURE_TAP_TO_WAKE, + FEATURE_TOUCH_HOVERING, + ); + + private static CMHardwareManager sCMHardwareManagerInstance; + + /** + * @hide to prevent subclassing from outside of the framework + */ + private CMHardwareManager(Context context) { + Context appContext = context.getApplicationContext(); + if (appContext != null) { + mContext = appContext; + } else { + mContext = context; + } + sService = getService(); + } + + /** + * Get or create an instance of the {@link cyanogenmod.hardware.CMHardwareManager} + * @param context + * @return {@link CMHardwareManager} + */ + public static CMHardwareManager getInstance(Context context) { + if (sCMHardwareManagerInstance == null) { + sCMHardwareManagerInstance = new CMHardwareManager(context); + } + return sCMHardwareManagerInstance; + } + + /** @hide */ + private static ICMHardwareService getService() { + if (sService != null) { + return sService; + } + IBinder b = ServiceManager.getService(CMContextConstants.CM_HARDWARE_SERVICE); + if (b != null) { + sService = ICMHardwareService.Stub.asInterface(b); + return sService; + } + return null; + } + + /** + * @return the supported features bitmask + */ + public int getSupportedFeatures() { + try { + return getService().getSupportedFeatures(); + } catch (RemoteException e) { + } + return 0; + } + + /** + * Determine if a CM Hardware feature is supported on this device + * + * @param feature The CM Hardware feature to query + * + * @return true if the feature is supported, false otherwise. + */ + public boolean isSupported(int feature) { + return feature == (getSupportedFeatures() & feature); + } + + /** + * Determine if the given feature is enabled or disabled. + * + * Only used for features which have simple enable/disable controls. + * + * @param feature the CM Hardware feature to query + * + * @return true if the feature is enabled, false otherwise. + */ + public boolean get(int feature) { + if (!BOOLEAN_FEATURES.contains(feature)) { + throw new IllegalArgumentException(feature + " is not a boolean"); + } + + try { + return getService().get(feature); + } catch (RemoteException e) { + } + return false; + } + + /** + * Enable or disable the given feature + * + * Only used for features which have simple enable/disable controls. + * + * @param feature the CM Hardware feature to set + * @param enable true to enable, false to disale + * + * @return true if the feature is enabled, false otherwise. + */ + public boolean set(int feature, boolean enable) { + if (!BOOLEAN_FEATURES.contains(feature)) { + throw new IllegalArgumentException(feature + " is not a boolean"); + } + + try { + return getService().set(feature, enable); + } catch (RemoteException e) { + } + return false; + } + + private int getArrayValue(int[] arr, int idx, int defaultValue) { + if (arr == null || arr.length <= idx) { + return defaultValue; + } + + return arr[idx]; + } + + /** + * {@hide} + */ + public static final int VIBRATOR_INTENSITY_INDEX = 0; + /** + * {@hide} + */ + public static final int VIBRATOR_DEFAULT_INDEX = 1; + /** + * {@hide} + */ + public static final int VIBRATOR_MIN_INDEX = 2; + /** + * {@hide} + */ + public static final int VIBRATOR_MAX_INDEX = 3; + /** + * {@hide} + */ + public static final int VIBRATOR_WARNING_INDEX = 4; + + private int[] getVibratorIntensityArray() { + try { + return getService().getVibratorIntensity(); + } catch (RemoteException e) { + } + return null; + } + + /** + * @return The current vibrator intensity. + */ + public int getVibratorIntensity() { + return getArrayValue(getVibratorIntensityArray(), VIBRATOR_INTENSITY_INDEX, 0); + } + + /** + * @return The default vibrator intensity. + */ + public int getVibratorDefaultIntensity() { + return getArrayValue(getVibratorIntensityArray(), VIBRATOR_DEFAULT_INDEX, 0); + } + + /** + * @return The minimum vibrator intensity. + */ + public int getVibratorMinIntensity() { + return getArrayValue(getVibratorIntensityArray(), VIBRATOR_MIN_INDEX, 0); + } + + /** + * @return The maximum vibrator intensity. + */ + public int getVibratorMaxIntensity() { + return getArrayValue(getVibratorIntensityArray(), VIBRATOR_MAX_INDEX, 0); + } + + /** + * @return The warning threshold vibrator intensity. + */ + public int getVibratorWarningIntensity() { + return getArrayValue(getVibratorIntensityArray(), VIBRATOR_WARNING_INDEX, 0); + } + + /** + * Set the current vibrator intensity + * + * @param intensity the intensity to set, between {@link #getVibratorMinIntensity()} and + * {@link #getVibratorMaxIntensity()} inclusive. + * + * @return true on success, false otherwise. + */ + public boolean setVibratorIntensity(int intensity) { + try { + return getService().setVibratorIntensity(intensity); + } catch (RemoteException e) { + } + return false; + } + + /** + * {@hide} + */ + public static final int COLOR_CALIBRATION_RED_INDEX = 0; + /** + * {@hide} + */ + public static final int COLOR_CALIBRATION_GREEN_INDEX = 1; + /** + * {@hide} + */ + public static final int COLOR_CALIBRATION_BLUE_INDEX = 2; + /** + * {@hide} + */ + public static final int COLOR_CALIBRATION_DEFAULT_INDEX = 3; + /** + * {@hide} + */ + public static final int COLOR_CALIBRATION_MIN_INDEX = 4; + /** + * {@hide} + */ + public static final int COLOR_CALIBRATION_MAX_INDEX = 5; + + private int[] getDisplayColorCalibrationArray() { + try { + return getService().getDisplayColorCalibration(); + } catch (RemoteException e) { + } + return null; + } + + /** + * @return the current RGB calibration, where int[0] = R, int[1] = G, int[2] = B. + */ + public int[] getDisplayColorCalibration() { + int[] arr = getDisplayColorCalibrationArray(); + if (arr == null || arr.length < 3) { + return null; + } + return Arrays.copyOf(arr, 3); + } + + /** + * @return the default value for all colors + */ + public int getDisplayColorCalibrationDefault() { + return getArrayValue(getDisplayColorCalibrationArray(), COLOR_CALIBRATION_DEFAULT_INDEX, 0); + } + + /** + * @return The minimum value for all colors + */ + public int getDisplayColorCalibrationMin() { + return getArrayValue(getDisplayColorCalibrationArray(), COLOR_CALIBRATION_MIN_INDEX, 0); + } + + /** + * @return The minimum value for all colors + */ + public int getDisplayColorCalibrationMax() { + return getArrayValue(getDisplayColorCalibrationArray(), COLOR_CALIBRATION_MAX_INDEX, 0); + } + + /** + * Set the display color calibration to the given rgb triplet + * + * @param rgb RGB color calibration. Each value must be between + * {@link getDisplayColorCalibrationMin()} and {@link getDisplayColorCalibrationMax()}, + * inclusive. + * + * @return true on success, false otherwise. + */ + public boolean setDisplayColorCalibration(int[] rgb) { + try { + return getService().setDisplayColorCalibration(rgb); + } catch (RemoteException e) { + } + return false; + } + + /** + * {@hide} + */ + public static final int GAMMA_CALIBRATION_RED_INDEX = 0; + /** + * {@hide} + */ + public static final int GAMMA_CALIBRATION_GREEN_INDEX = 1; + /** + * {@hide} + */ + public static final int GAMMA_CALIBRATION_BLUE_INDEX = 2; + /** + * {@hide} + */ + public static final int GAMMA_CALIBRATION_MIN_INDEX = 3; + /** + * {@hide} + */ + public static final int GAMMA_CALIBRATION_MAX_INDEX = 4; + + private int[] getDisplayGammaCalibrationArray(int idx) { + try { + return getService().getDisplayGammaCalibration(idx); + } catch (RemoteException e) { + } + return null; + } + + /** + * @return the number of RGB controls the device supports + */ + public int getNumGammaControls() { + try { + return getService().getNumGammaControls(); + } catch (RemoteException e) { + } + return 0; + } + + /** + * @param the control to query + * + * @return the current RGB gamma calibration for the given control + */ + public int[] getDisplayGammaCalibration(int idx) { + int[] arr = getDisplayGammaCalibrationArray(idx); + if (arr == null || arr.length < 3) { + return null; + } + return Arrays.copyOf(arr, 3); + } + + /** + * @return the minimum value for all colors + */ + public int getDisplayGammaCalibrationMin() { + return getArrayValue(getDisplayGammaCalibrationArray(0), GAMMA_CALIBRATION_MIN_INDEX, 0); + } + + /** + * @return the maximum value for all colors + */ + public int getDisplayGammaCalibrationMax() { + return getArrayValue(getDisplayGammaCalibrationArray(0), GAMMA_CALIBRATION_MAX_INDEX, 0); + } + + /** + * Set the display gamma calibration for a specific control + * + * @param idx the control to set + * @param rgb RGB color calibration. Each value must be between + * {@link getDisplayGammaCalibrationMin()} and {@link getDisplayGammaCalibrationMax()}, + * inclusive. + * + * @return true on success, false otherwise. + */ + public boolean setDisplayGammaCalibration(int idx, int[] rgb) { + try { + return getService().setDisplayGammaCalibration(idx, rgb); + } catch (RemoteException e) { + } + return false; + } + + /** + * @return the source location of LTO data, or null on failure + */ + public String getLtoSource() { + try { + return getService().getLtoSource(); + } catch (RemoteException e) { + } + return null; + } + + /** + * @return the destination location of LTO data, or null on failure + */ + public String getLtoDestination() { + try { + return getService().getLtoDestination(); + } catch (RemoteException e) { + } + return null; + } + + /** + * @return the interval, in milliseconds, to trigger LTO data download + */ + public long getLtoDownloadInterval() { + try { + return getService().getLtoDownloadInterval(); + } catch (RemoteException e) { + } + return 0; + } + + /** + * @return the serial number to display instead of ro.serialno, or null on failure + */ + public String getSerialNumber() { + try { + return getService().getSerialNumber(); + } catch (RemoteException e) { + } + return null; + } + + /** + * @return true if adaptive backlight should be enabled when sunlight enhancement + * is enabled. + */ + public boolean requireAdaptiveBacklightForSunlightEnhancement() { + try { + return getService().requireAdaptiveBacklightForSunlightEnhancement(); + } catch (RemoteException e) { + } + return false; + } +} diff --git a/src/java/cyanogenmod/hardware/ICMHardwareService.aidl b/src/java/cyanogenmod/hardware/ICMHardwareService.aidl new file mode 100644 index 0000000..ef85d94 --- /dev/null +++ b/src/java/cyanogenmod/hardware/ICMHardwareService.aidl @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2015, The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cyanogenmod.hardware; + +/** @hide */ +interface ICMHardwareService { + + int getSupportedFeatures(); + boolean get(int feature); + boolean set(int feature, boolean enable); + + int[] getDisplayColorCalibration(); + boolean setDisplayColorCalibration(in int[] rgb); + + int getNumGammaControls(); + int[] getDisplayGammaCalibration(int idx); + boolean setDisplayGammaCalibration(int idx, in int[] rgb); + + int[] getVibratorIntensity(); + boolean setVibratorIntensity(int intensity); + + String getLtoSource(); + String getLtoDestination(); + long getLtoDownloadInterval(); + + String getSerialNumber(); + + boolean requireAdaptiveBacklightForSunlightEnhancement(); +}