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 17package com.android.car.systeminterface; 18 19import android.content.ContentResolver; 20import android.content.Context; 21import android.database.ContentObserver; 22import android.hardware.display.DisplayManager; 23import android.hardware.display.DisplayManager.DisplayListener; 24import android.os.Handler; 25import android.os.Looper; 26import android.os.PowerManager; 27import android.os.SystemClock; 28import android.provider.Settings.SettingNotFoundException; 29import android.provider.Settings.System; 30import android.util.Log; 31import android.view.Display; 32 33import com.android.car.CarLog; 34import com.android.car.CarPowerManagementService; 35 36/** 37 * Interface that abstracts display operations 38 */ 39public interface DisplayInterface { 40 /** 41 * @param brightness Level from 0 to 100% 42 */ 43 void setDisplayBrightness(int brightness); 44 void setDisplayState(boolean on); 45 void startDisplayStateMonitoring(CarPowerManagementService service); 46 void stopDisplayStateMonitoring(); 47 48 class DefaultImpl implements DisplayInterface { 49 private final ContentResolver mContentResolver; 50 private final Context mContext; 51 private final DisplayManager mDisplayManager; 52 private final int mMaximumBacklight; 53 private final int mMinimumBacklight; 54 private final PowerManager mPowerManager; 55 private final WakeLockInterface mWakeLockInterface; 56 private CarPowerManagementService mService; 57 private boolean mDisplayStateSet; 58 59 private ContentObserver mBrightnessObserver = 60 new ContentObserver(new Handler(Looper.getMainLooper())) { 61 @Override 62 public void onChange(boolean selfChange) { 63 int brightness = mMinimumBacklight; 64 int range = mMaximumBacklight - mMinimumBacklight; 65 66 try { 67 brightness = System.getInt(mContentResolver, System.SCREEN_BRIGHTNESS); 68 } catch (SettingNotFoundException e) { 69 Log.e(CarLog.TAG_POWER, "Could not get SCREEN_BRIGHTNESS: " + e); 70 } 71 // Convert brightness from 0-255 to 0-100% 72 brightness -= mMinimumBacklight; 73 brightness *= 100; 74 brightness += (range + 1) / 2; 75 brightness /= range; 76 mService.sendDisplayBrightness(brightness); 77 } 78 }; 79 80 private final DisplayManager.DisplayListener mDisplayListener = new DisplayListener() { 81 @Override 82 public void onDisplayAdded(int displayId) { 83 //ignore 84 } 85 86 @Override 87 public void onDisplayRemoved(int displayId) { 88 //ignore 89 } 90 91 @Override 92 public void onDisplayChanged(int displayId) { 93 if (displayId == Display.DEFAULT_DISPLAY) { 94 handleMainDisplayChanged(); 95 } 96 } 97 }; 98 99 DefaultImpl(Context context, WakeLockInterface wakeLockInterface) { 100 mContext = context; 101 mContentResolver = mContext.getContentResolver(); 102 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); 103 mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 104 mMaximumBacklight = mPowerManager.getMaximumScreenBrightnessSetting(); 105 mMinimumBacklight = mPowerManager.getMinimumScreenBrightnessSetting(); 106 mWakeLockInterface = wakeLockInterface; 107 } 108 109 private void handleMainDisplayChanged() { 110 boolean isOn = isMainDisplayOn(); 111 CarPowerManagementService service; 112 synchronized (this) { 113 if (mDisplayStateSet == isOn) { // same as what is set 114 return; 115 } 116 service = mService; 117 } 118 service.handleMainDisplayChanged(isOn); 119 } 120 121 private boolean isMainDisplayOn() { 122 Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); 123 return disp.getState() == Display.STATE_ON; 124 } 125 126 @Override 127 public void setDisplayBrightness(int brightness) { 128 // Brightness is set in percent. Need to convert this into 0-255 scale. The actual 129 // brightness algorithm should look like this: 130 // 131 // newBrightness = (brightness * (max - min)) + min 132 // 133 // Since we're using integer arithmetic, do the multiplication first, then add 50 to 134 // round up as needed. 135 brightness *= mMaximumBacklight - mMinimumBacklight; // Multiply by full range 136 brightness += 50; // Integer rounding 137 brightness /= 100; // Divide by 100 138 brightness += mMinimumBacklight; 139 // Range checking 140 if (brightness < mMinimumBacklight) { 141 brightness = mMinimumBacklight; 142 } else if (brightness > mMaximumBacklight) { 143 brightness = mMaximumBacklight; 144 } 145 // Set the brightness 146 System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, brightness); 147 } 148 149 @Override 150 public void startDisplayStateMonitoring(CarPowerManagementService service) { 151 synchronized (this) { 152 mService = service; 153 mDisplayStateSet = isMainDisplayOn(); 154 } 155 mContentResolver.registerContentObserver(System.getUriFor(System.SCREEN_BRIGHTNESS), 156 false, mBrightnessObserver); 157 mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler()); 158 } 159 160 @Override 161 public void stopDisplayStateMonitoring() { 162 mDisplayManager.unregisterDisplayListener(mDisplayListener); 163 mContentResolver.unregisterContentObserver(mBrightnessObserver); 164 } 165 166 @Override 167 public void setDisplayState(boolean on) { 168 synchronized (this) { 169 mDisplayStateSet = on; 170 } 171 if (on) { 172 mWakeLockInterface.switchToFullWakeLock(); 173 Log.i(CarLog.TAG_POWER, "on display"); 174 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 175 } else { 176 mWakeLockInterface.switchToPartialWakeLock(); 177 Log.i(CarLog.TAG_POWER, "off display"); 178 mPowerManager.goToSleep(SystemClock.uptimeMillis()); 179 } 180 } 181 } 182} 183