replicant-vendor_cmsdk/cm/lib/main/java/org/cyanogenmod/platform/internal/display/OutdoorModeController.java

218 lines
7.0 KiB
Java

/*
* Copyright (C) 2016 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.display;
import static cyanogenmod.hardware.LiveDisplayManager.MODE_AUTO;
import static cyanogenmod.hardware.LiveDisplayManager.MODE_DAY;
import static cyanogenmod.hardware.LiveDisplayManager.MODE_OUTDOOR;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import com.android.server.twilight.TwilightState;
import java.io.PrintWriter;
import java.util.BitSet;
import cyanogenmod.hardware.CMHardwareManager;
import cyanogenmod.hardware.LiveDisplayManager;
import cyanogenmod.providers.CMSettings;
public class OutdoorModeController extends LiveDisplayFeature {
private CMHardwareManager mHardware;
private AmbientLuxObserver mLuxObserver;
// hardware capabilities
private boolean mUseOutdoorMode;
private boolean mSelfManaged;
// default values
private int mDefaultOutdoorLux;
private boolean mDefaultAutoOutdoorMode;
// current values
private boolean mAutoOutdoorMode;
// internal state
private boolean mIsOutdoor;
private boolean mIsSensorEnabled;
// sliding window for sensor event smoothing
private static final int SENSOR_WINDOW_MS = 3000;
public OutdoorModeController(Context context, Handler handler) {
super(context, handler);
}
@Override
public boolean onStart() {
mHardware = CMHardwareManager.getInstance(mContext);
if (!mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT)) {
return false;
}
mUseOutdoorMode = true;
mDefaultOutdoorLux = mContext.getResources().getInteger(
org.cyanogenmod.platform.internal.R.integer.config_outdoorAmbientLux);
mDefaultAutoOutdoorMode = mContext.getResources().getBoolean(
org.cyanogenmod.platform.internal.R.bool.config_defaultAutoOutdoorMode);
mSelfManaged = mHardware.isSunlightEnhancementSelfManaged();
if (!mSelfManaged) {
mLuxObserver = new AmbientLuxObserver(mContext, mHandler.getLooper(),
mDefaultOutdoorLux, SENSOR_WINDOW_MS);
}
registerSettings(
CMSettings.System.getUriFor(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE));
return true;
}
@Override
void getCapabilities(final BitSet caps) {
if (mUseOutdoorMode) {
caps.set(LiveDisplayManager.MODE_OUTDOOR);
if (mSelfManaged) {
caps.set(LiveDisplayManager.FEATURE_MANAGED_OUTDOOR_MODE);
}
}
}
@Override
public void onModeChanged(int mode) {
super.onModeChanged(mode);
updateOutdoorMode();
}
@Override
public void onDisplayStateChanged(boolean screenOn) {
super.onDisplayStateChanged(screenOn);
if (mSelfManaged) {
return;
}
updateOutdoorMode();
}
@Override
public void onLowPowerModeChanged(boolean lowPowerMode) {
super.onLowPowerModeChanged(lowPowerMode);
updateOutdoorMode();
}
@Override
public synchronized void onSettingsChanged(Uri uri) {
mAutoOutdoorMode = getInt(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE,
(mDefaultAutoOutdoorMode ? 1 : 0)) == 1;
updateOutdoorMode();
}
@Override
public void onTwilightUpdated(TwilightState twilight) {
super.onTwilightUpdated(twilight);
updateOutdoorMode();
}
@Override
public void dump(PrintWriter pw) {
pw.println();
pw.println("OutdoorModeController Configuration:");
pw.println(" mSelfManaged=" + mSelfManaged);
if (!mSelfManaged) {
pw.println(" mDefaultOutdoorLux=" + mDefaultOutdoorLux);
pw.println();
pw.println(" OutdoorModeController State:");
pw.println(" mAutoOutdoorMode=" + mAutoOutdoorMode);
pw.println(" mIsOutdoor=" + mIsOutdoor);
pw.println(" mIsNight=" + isNight());
}
mLuxObserver.dump(pw);
}
boolean setAutomaticOutdoorModeEnabled(boolean enabled) {
if (!mUseOutdoorMode) {
return false;
}
putInt(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, (enabled ? 1 : 0));
return true;
}
boolean isAutomaticOutdoorModeEnabled() {
return mUseOutdoorMode;
}
boolean getDefaultAutoOutdoorMode() {
return mDefaultAutoOutdoorMode;
}
private void observeAmbientLuxLocked(boolean observe) {
mLuxObserver.setTransitionListener(observe ? mListener : null);
}
/**
* Outdoor mode is optionally enabled when ambient lux > 10000 and it's daytime
* Melt faces!
*
* TODO: Use the camera or RGB sensor to determine if it's really sunlight
*/
private synchronized void updateOutdoorMode() {
/*
* Hardware toggle:
* Enabled if outdoor mode explictly selected
* Enabled if outdoor lux exceeded and day mode or auto mode (if not night)
*/
boolean enabled = !isLowPowerMode() &&
(getMode() == MODE_OUTDOOR ||
(mAutoOutdoorMode && (mSelfManaged || mIsOutdoor) &&
((getMode() == MODE_AUTO && !isNight()) || getMode() == MODE_DAY)));
mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, enabled);
/* Sensor:
* Enabled in day mode
* Enabled in auto mode if it's not night
* Disabled if outdoor mode explicitly selected
* Disabled in low power mode
* Disabled if screen is off
*/
boolean sensorEnabled = !isLowPowerMode() && isScreenOn() &&
getMode() != MODE_OUTDOOR && mAutoOutdoorMode &&
((getMode() == MODE_AUTO && !isNight()) || getMode() == MODE_DAY);
if (mIsSensorEnabled != sensorEnabled) {
mIsSensorEnabled = sensorEnabled;
observeAmbientLuxLocked(sensorEnabled);
}
}
private final AmbientLuxObserver.TransitionListener mListener =
new AmbientLuxObserver.TransitionListener() {
@Override
public void onTransition(final int state, float ambientLux) {
final boolean outdoor = state == 1;
synchronized (OutdoorModeController.this) {
if (mIsOutdoor == outdoor) {
return;
}
mIsOutdoor = outdoor;
updateOutdoorMode();
}
}
};
}