1 /* 2 * Copyright (C) 2016 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.car; 18 19 import android.annotation.IntDef; 20 import android.app.UiModeManager; 21 import android.car.hardware.CarPropertyValue; 22 import android.car.hardware.property.CarPropertyEvent; 23 import android.car.hardware.property.ICarPropertyEventListener; 24 import android.content.Context; 25 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 26 import android.os.RemoteException; 27 import android.util.IndentingPrintWriter; 28 import android.util.Slog; 29 30 import com.android.internal.annotations.GuardedBy; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.List; 35 36 /** 37 * Class used to handle events used to set vehicle in night mode. 38 */ 39 public class CarNightService implements CarServiceBase { 40 41 public static final boolean DBG = false; 42 43 @IntDef({FORCED_SENSOR_MODE, FORCED_DAY_MODE, FORCED_NIGHT_MODE}) 44 @Retention(RetentionPolicy.SOURCE) 45 public @interface DayNightSensorMode {} 46 47 public static final int FORCED_SENSOR_MODE = 0; 48 public static final int FORCED_DAY_MODE = 1; 49 public static final int FORCED_NIGHT_MODE = 2; 50 51 private final Object mLock = new Object(); 52 @GuardedBy("mLock") 53 private int mNightSetting = UiModeManager.MODE_NIGHT_YES; 54 @GuardedBy("mLock") 55 private int mForcedMode = FORCED_SENSOR_MODE; 56 @GuardedBy("mLock") 57 private long mLastSensorEventTime = -1; 58 private final Context mContext; 59 @GuardedBy("mLock") 60 private final UiModeManager mUiModeManager; 61 private final CarPropertyService mCarPropertyService; 62 63 private final ICarPropertyEventListener mICarPropertyEventListener = 64 new ICarPropertyEventListener.Stub() { 65 @Override 66 public void onEvent(List<CarPropertyEvent> events) throws RemoteException { 67 synchronized (mLock) { 68 for (CarPropertyEvent event : events) { 69 onNightModeCarPropertyEventLocked(event); 70 } 71 } 72 } 73 }; 74 75 /** 76 * Acts on {@link CarPropertyEvent} events marked with 77 * {@link CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE} and marked with {@link 78 * VehicleProperty.NIGHT_MODE} by 79 * setting the vehicle in night mode. 80 * <p> 81 * This method does nothing if the event parameter is {@code null}. 82 * 83 * @param event the car property event to be handled 84 */ 85 @GuardedBy("mLock") onNightModeCarPropertyEventLocked(CarPropertyEvent event)86 private void onNightModeCarPropertyEventLocked(CarPropertyEvent event) { 87 if (event == null) { 88 return; 89 } 90 if (event.getEventType() == CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE) { 91 // Only handle onChange events 92 CarPropertyValue value = event.getCarPropertyValue(); 93 if (value.getPropertyId() == VehicleProperty.NIGHT_MODE 94 && value.getTimestamp() > mLastSensorEventTime) { 95 mLastSensorEventTime = value.getTimestamp(); 96 boolean nightMode = (Boolean) value.getValue(); 97 Slog.i(CarLog.TAG_SENSOR, "Set dayNight Mode as " 98 + nightMode + " at timestamp: " + mLastSensorEventTime); 99 setNightModeLocked(nightMode); 100 } 101 } 102 } 103 104 @GuardedBy("mLock") setNightModeLocked(boolean nightMode)105 private void setNightModeLocked(boolean nightMode) { 106 if (nightMode) { 107 mNightSetting = UiModeManager.MODE_NIGHT_YES; 108 if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent NIGHT"); 109 } else { 110 mNightSetting = UiModeManager.MODE_NIGHT_NO; 111 if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent DAY"); 112 } 113 if (mUiModeManager != null && (mForcedMode == FORCED_SENSOR_MODE)) { 114 mUiModeManager.setNightMode(mNightSetting); 115 if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent APPLIED"); 116 } else { 117 if (DBG) Slog.d(CarLog.TAG_SENSOR, "CAR dayNight handleSensorEvent IGNORED"); 118 } 119 } 120 121 /** 122 * Sets {@link UiModeManager} to night mode according to the {@link DayNightSensorMode} passed 123 * as parameter. 124 * 125 * @param mode the sensor mode used to set vehicle in night mode 126 * @return the current night mode, or {@code -1} on error 127 */ forceDayNightMode(@ayNightSensorMode int mode)128 public int forceDayNightMode(@DayNightSensorMode int mode) { 129 synchronized (mLock) { 130 if (mUiModeManager == null) { 131 return -1; 132 } 133 int resultMode; 134 switch (mode) { 135 case FORCED_SENSOR_MODE: 136 resultMode = mNightSetting; 137 mForcedMode = FORCED_SENSOR_MODE; 138 break; 139 case FORCED_DAY_MODE: 140 resultMode = UiModeManager.MODE_NIGHT_NO; 141 mForcedMode = FORCED_DAY_MODE; 142 break; 143 case FORCED_NIGHT_MODE: 144 resultMode = UiModeManager.MODE_NIGHT_YES; 145 mForcedMode = FORCED_NIGHT_MODE; 146 break; 147 default: 148 Slog.e(CarLog.TAG_SENSOR, "Unknown forced day/night mode " + mode); 149 return -1; 150 } 151 mUiModeManager.setNightMode(resultMode); 152 return mUiModeManager.getNightMode(); 153 } 154 } 155 CarNightService(Context context, CarPropertyService propertyService)156 CarNightService(Context context, CarPropertyService propertyService) { 157 mContext = context; 158 mCarPropertyService = propertyService; 159 mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); 160 if (mUiModeManager == null) { 161 Slog.w(CarLog.TAG_SENSOR, "Failed to get UI_MODE_SERVICE"); 162 } 163 } 164 165 @Override init()166 public void init() { 167 if (DBG) { 168 Slog.d(CarLog.TAG_SENSOR, "CAR dayNight init."); 169 } 170 synchronized (mLock) { 171 mCarPropertyService.registerListener(VehicleProperty.NIGHT_MODE, 0, 172 mICarPropertyEventListener); 173 CarPropertyValue propertyValue = mCarPropertyService.getPropertySafe( 174 VehicleProperty.NIGHT_MODE, 0); 175 if (propertyValue != null && propertyValue.getTimestamp() != 0) { 176 mLastSensorEventTime = propertyValue.getTimestamp(); 177 setNightModeLocked((Boolean) propertyValue.getValue()); 178 } else { 179 Slog.w(CarLog.TAG_SENSOR, "Failed to get value of NIGHT_MODE"); 180 setNightModeLocked(true); 181 } 182 } 183 } 184 185 @Override release()186 public void release() { 187 } 188 189 @Override dump(IndentingPrintWriter writer)190 public void dump(IndentingPrintWriter writer) { 191 synchronized (mLock) { 192 writer.println("*DAY NIGHT POLICY*"); 193 writer.println( 194 "Mode:" + ((mNightSetting == UiModeManager.MODE_NIGHT_YES) ? "night" : "day")); 195 writer.println("Forced Mode? " + (mForcedMode == FORCED_SENSOR_MODE 196 ? "false, timestamp of dayNight sensor is: " + mLastSensorEventTime 197 : (mForcedMode == FORCED_DAY_MODE ? "day" : "night"))); 198 } 199 } 200 } 201 202