/* * Copyright (C) 2016 The Android Open Source 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 com.android.car; import android.annotation.IntDef; import android.app.UiModeManager; import android.car.hardware.CarPropertyValue; import android.car.hardware.property.CarPropertyEvent; import android.car.hardware.property.ICarPropertyEventListener; import android.content.Context; import android.hardware.automotive.vehicle.V2_0.VehicleProperty; import android.os.RemoteException; import android.util.IndentingPrintWriter; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; /** * Class used to handle events used to set vehicle in night mode. */ public class CarNightService implements CarServiceBase { public static final boolean DBG = false; @IntDef({FORCED_SENSOR_MODE, FORCED_DAY_MODE, FORCED_NIGHT_MODE}) @Retention(RetentionPolicy.SOURCE) public @interface DayNightSensorMode {} public static final int FORCED_SENSOR_MODE = 0; public static final int FORCED_DAY_MODE = 1; public static final int FORCED_NIGHT_MODE = 2; private final Object mLock = new Object(); @GuardedBy("mLock") private int mNightSetting = UiModeManager.MODE_NIGHT_YES; @GuardedBy("mLock") private int mForcedMode = FORCED_SENSOR_MODE; @GuardedBy("mLock") private long mLastSensorEventTime = -1; private final Context mContext; @GuardedBy("mLock") private final UiModeManager mUiModeManager; private final CarPropertyService mCarPropertyService; private final ICarPropertyEventListener mICarPropertyEventListener = new ICarPropertyEventListener.Stub() { @Override public void onEvent(List events) throws RemoteException { synchronized (mLock) { for (CarPropertyEvent event : events) { onNightModeCarPropertyEventLocked(event); } } } }; /** * Acts on {@link CarPropertyEvent} events marked with * {@link CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE} and marked with {@link * VehicleProperty.NIGHT_MODE} by * setting the vehicle in night mode. *

* This method does nothing if the event parameter is {@code null}. * * @param event the car property event to be handled */ @GuardedBy("mLock") private void onNightModeCarPropertyEventLocked(CarPropertyEvent event) { if (event == null) { return; } if (event.getEventType() == CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE) { // Only handle onChange events CarPropertyValue value = event.getCarPropertyValue(); if (value.getPropertyId() == VehicleProperty.NIGHT_MODE && value.getTimestamp() > mLastSensorEventTime) { mLastSensorEventTime = value.getTimestamp(); boolean nightMode = (Boolean) value.getValue(); Slog.i(CarLog.TAG_SENSOR, "Set dayNight Mode as " + nightMode + " at timestamp: " + mLastSensorEventTime); setNightModeLocked(nightMode); } } } @GuardedBy("mLock") private void setNightModeLocked(boolean nightMode) { if (nightMode) { mNightSetting = UiModeManager.MODE_NIGHT_YES; if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent NIGHT"); } else { mNightSetting = UiModeManager.MODE_NIGHT_NO; if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent DAY"); } if (mUiModeManager != null && (mForcedMode == FORCED_SENSOR_MODE)) { mUiModeManager.setNightMode(mNightSetting); if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent APPLIED"); } else { if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent IGNORED"); } } /** * Sets {@link UiModeManager} to night mode according to the {@link DayNightSensorMode} passed * as parameter. * * @param mode the sensor mode used to set vehicle in night mode * @return the current night mode, or {@code -1} on error */ public int forceDayNightMode(@DayNightSensorMode int mode) { synchronized (mLock) { if (mUiModeManager == null) { return -1; } int resultMode; switch (mode) { case FORCED_SENSOR_MODE: resultMode = mNightSetting; mForcedMode = FORCED_SENSOR_MODE; break; case FORCED_DAY_MODE: resultMode = UiModeManager.MODE_NIGHT_NO; mForcedMode = FORCED_DAY_MODE; break; case FORCED_NIGHT_MODE: resultMode = UiModeManager.MODE_NIGHT_YES; mForcedMode = FORCED_NIGHT_MODE; break; default: Slog.e(CarLog.TAG_SENSOR, "Unknown forced day/night mode " + mode); return -1; } mUiModeManager.setNightMode(resultMode); return mUiModeManager.getNightMode(); } } CarNightService(Context context, CarPropertyService propertyService) { mContext = context; mCarPropertyService = propertyService; mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); if (mUiModeManager == null) { Slog.w(CarLog.TAG_SENSOR, "Failed to get UI_MODE_SERVICE"); } } @Override public void init() { if (DBG) { Slog.d(CarLog.TAG_SENSOR, "CAR dayNight init."); } synchronized (mLock) { mCarPropertyService.registerListener(VehicleProperty.NIGHT_MODE, 0, mICarPropertyEventListener); CarPropertyValue propertyValue = mCarPropertyService.getPropertySafe( VehicleProperty.NIGHT_MODE, 0); if (propertyValue != null && propertyValue.getTimestamp() != 0) { mLastSensorEventTime = propertyValue.getTimestamp(); setNightModeLocked((Boolean) propertyValue.getValue()); } else { Slog.w(CarLog.TAG_SENSOR, "Failed to get value of NIGHT_MODE"); setNightModeLocked(true); } } } @Override public void release() { } @Override public void dump(IndentingPrintWriter writer) { synchronized (mLock) { writer.println("*DAY NIGHT POLICY*"); writer.println( "Mode:" + ((mNightSetting == UiModeManager.MODE_NIGHT_YES) ? "night" : "day")); writer.println("Forced Mode? " + (mForcedMode == FORCED_SENSOR_MODE ? "false, timestamp of dayNight sensor is: " + mLastSensorEventTime : (mForcedMode == FORCED_DAY_MODE ? "day" : "night"))); } } }