1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 package com.android.settings.display; 15 16 import static android.content.Intent.ACTION_SHOW_BRIGHTNESS_DIALOG; 17 18 import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX; 19 import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN; 20 import static com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat; 21 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.database.ContentObserver; 26 import android.hardware.display.BrightnessInfo; 27 import android.hardware.display.DisplayManager; 28 import android.hardware.display.DisplayManager.DisplayListener; 29 import android.net.Uri; 30 import android.os.Handler; 31 import android.os.Looper; 32 import android.os.PowerManager; 33 import android.os.RemoteException; 34 import android.os.ServiceManager; 35 import android.provider.Settings.System; 36 import android.service.vr.IVrManager; 37 import android.text.TextUtils; 38 import android.util.Log; 39 40 import androidx.annotation.VisibleForTesting; 41 import androidx.preference.Preference; 42 import androidx.preference.PreferenceScreen; 43 44 import com.android.settings.core.PreferenceControllerMixin; 45 import com.android.settings.core.SettingsBaseActivity; 46 import com.android.settingslib.core.AbstractPreferenceController; 47 import com.android.settingslib.core.lifecycle.Lifecycle; 48 import com.android.settingslib.core.lifecycle.LifecycleObserver; 49 import com.android.settingslib.core.lifecycle.events.OnStart; 50 import com.android.settingslib.core.lifecycle.events.OnStop; 51 import com.android.settingslib.transition.SettingsTransitionHelper; 52 53 import java.text.NumberFormat; 54 55 public class BrightnessLevelPreferenceController extends AbstractPreferenceController implements 56 PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop { 57 58 private static final String TAG = "BrightnessPrefCtrl"; 59 private static final String KEY_BRIGHTNESS = "brightness"; 60 private static final Uri BRIGHTNESS_FOR_VR_URI; 61 private static final Uri BRIGHTNESS_ADJ_URI; 62 63 private final float mMinVrBrightness; 64 private final float mMaxVrBrightness; 65 private final ContentResolver mContentResolver; 66 private final Handler mHandler = new Handler(Looper.getMainLooper()); 67 private final DisplayManager mDisplayManager; 68 69 private Preference mPreference; 70 71 static { 72 BRIGHTNESS_FOR_VR_URI = System.getUriFor(System.SCREEN_BRIGHTNESS_FOR_VR); 73 BRIGHTNESS_ADJ_URI = System.getUriFor(System.SCREEN_AUTO_BRIGHTNESS_ADJ); 74 } 75 76 private ContentObserver mBrightnessObserver = 77 new ContentObserver(mHandler) { 78 @Override 79 public void onChange(boolean selfChange) { 80 updatedSummary(mPreference); 81 } 82 }; 83 84 private final DisplayListener mDisplayListener = new DisplayListener() { 85 @Override 86 public void onDisplayAdded(int displayId) { 87 } 88 89 @Override 90 public void onDisplayRemoved(int displayId) { 91 } 92 93 @Override 94 public void onDisplayChanged(int displayId) { 95 updatedSummary(mPreference); 96 } 97 }; 98 99 BrightnessLevelPreferenceController(Context context, Lifecycle lifecycle)100 public BrightnessLevelPreferenceController(Context context, Lifecycle lifecycle) { 101 super(context); 102 mDisplayManager = context.getSystemService(DisplayManager.class); 103 104 if (lifecycle != null) { 105 lifecycle.addObserver(this); 106 } 107 final PowerManager powerManager = context.getSystemService(PowerManager.class); 108 109 mMinVrBrightness = powerManager.getBrightnessConstraint( 110 PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR); 111 mMaxVrBrightness = powerManager.getBrightnessConstraint( 112 PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR); 113 mContentResolver = mContext.getContentResolver(); 114 } 115 116 @Override isAvailable()117 public boolean isAvailable() { 118 return true; 119 } 120 121 @Override getPreferenceKey()122 public String getPreferenceKey() { 123 return KEY_BRIGHTNESS; 124 } 125 126 @Override displayPreference(PreferenceScreen screen)127 public void displayPreference(PreferenceScreen screen) { 128 super.displayPreference(screen); 129 mPreference = screen.findPreference(KEY_BRIGHTNESS); 130 } 131 132 @Override updateState(Preference preference)133 public void updateState(Preference preference) { 134 updatedSummary(preference); 135 } 136 137 @Override onStart()138 public void onStart() { 139 mContentResolver.registerContentObserver(BRIGHTNESS_FOR_VR_URI, false, mBrightnessObserver); 140 mContentResolver.registerContentObserver(BRIGHTNESS_ADJ_URI, false, mBrightnessObserver); 141 mDisplayManager.registerDisplayListener(mDisplayListener, mHandler, 142 DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS); 143 } 144 145 @Override onStop()146 public void onStop() { 147 mContentResolver.unregisterContentObserver(mBrightnessObserver); 148 mDisplayManager.unregisterDisplayListener(mDisplayListener); 149 } 150 151 @Override handlePreferenceTreeClick(Preference preference)152 public boolean handlePreferenceTreeClick(Preference preference) { 153 if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { 154 return false; 155 } 156 final Intent intent = new Intent(ACTION_SHOW_BRIGHTNESS_DIALOG); 157 intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE, 158 SettingsTransitionHelper.TransitionType.TRANSITION_NONE); 159 mContext.startActivity(intent); 160 return true; 161 } 162 updatedSummary(Preference preference)163 private void updatedSummary(Preference preference) { 164 if (preference != null) { 165 preference.setSummary(NumberFormat.getPercentInstance().format(getCurrentBrightness())); 166 } 167 } 168 getCurrentBrightness()169 private double getCurrentBrightness() { 170 int value = 0; 171 if (isInVrMode()) { 172 value = convertLinearToGammaFloat(System.getFloat(mContentResolver, 173 System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mMaxVrBrightness), 174 mMinVrBrightness, mMaxVrBrightness); 175 } else { 176 final BrightnessInfo info = mContext.getDisplay().getBrightnessInfo(); 177 if (info != null) { 178 value = convertLinearToGammaFloat(info.brightness, info.brightnessMinimum, 179 info.brightnessMaximum); 180 } 181 } 182 return getPercentage(value, GAMMA_SPACE_MIN, GAMMA_SPACE_MAX); 183 } 184 getPercentage(double value, int min, int max)185 private double getPercentage(double value, int min, int max) { 186 if (value > max) { 187 return 1.0; 188 } 189 if (value < min) { 190 return 0.0; 191 } 192 return (value - min) / (max - min); 193 } 194 195 @VisibleForTesting safeGetVrManager()196 IVrManager safeGetVrManager() { 197 return IVrManager.Stub.asInterface(ServiceManager.getService( 198 Context.VR_SERVICE)); 199 } 200 201 @VisibleForTesting isInVrMode()202 boolean isInVrMode() { 203 IVrManager vrManager = safeGetVrManager(); 204 if (vrManager != null) { 205 try { 206 return vrManager.getVrModeState(); 207 } catch (RemoteException e) { 208 Log.e(TAG, "Failed to check vr mode!", e); 209 } 210 } 211 return false; 212 } 213 } 214