1 /* 2 * Copyright (C) 2018 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.settings.display; 18 19 import static android.os.UserManager.DISALLOW_CONFIG_BRIGHTNESS; 20 21 import static com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment.DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG; 22 import static com.android.car.settings.enterprise.EnterpriseUtils.hasUserRestrictionByDpm; 23 import static com.android.car.settings.enterprise.EnterpriseUtils.hasUserRestrictionByUm; 24 import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX; 25 import static com.android.settingslib.display.BrightnessUtils.convertGammaToLinear; 26 import static com.android.settingslib.display.BrightnessUtils.convertLinearToGamma; 27 28 import android.car.drivingstate.CarUxRestrictions; 29 import android.content.Context; 30 import android.database.ContentObserver; 31 import android.hardware.display.DisplayManager; 32 import android.net.Uri; 33 import android.os.Handler; 34 import android.os.Looper; 35 import android.os.PowerManager; 36 import android.os.UserHandle; 37 import android.os.UserManager; 38 import android.provider.Settings; 39 import android.widget.Toast; 40 41 import androidx.annotation.VisibleForTesting; 42 43 import com.android.car.settings.CarSettingsApplication; 44 import com.android.car.settings.R; 45 import com.android.car.settings.common.FragmentController; 46 import com.android.car.settings.common.Logger; 47 import com.android.car.settings.common.PreferenceController; 48 import com.android.car.settings.common.SeekBarPreference; 49 import com.android.car.settings.enterprise.EnterpriseUtils; 50 import com.android.internal.display.BrightnessSynchronizer; 51 52 /** Business logic for changing the brightness of the display. */ 53 public class BrightnessLevelPreferenceController extends PreferenceController<SeekBarPreference> { 54 55 private static final Logger LOG = new Logger(BrightnessLevelPreferenceController.class); 56 private static final Uri BRIGHTNESS_URI = Settings.System.getUriFor( 57 Settings.System.SCREEN_BRIGHTNESS); 58 private final Handler mHandler = new Handler(Looper.getMainLooper()); 59 60 private final ContentObserver mBrightnessObserver = new ContentObserver(mHandler) { 61 @Override 62 public void onChange(boolean selfChange) { 63 refreshUi(); 64 } 65 }; 66 67 @VisibleForTesting 68 final int mMaximumBacklight; 69 @VisibleForTesting 70 final int mMinimumBacklight; 71 private final boolean mIsVisibleBackgroundUsersSupported; 72 private DisplayManager mDisplayManager; 73 BrightnessLevelPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)74 public BrightnessLevelPreferenceController(Context context, String preferenceKey, 75 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 76 super(context, preferenceKey, fragmentController, uxRestrictions); 77 78 PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 79 mMaximumBacklight = powerManager.getMaximumScreenBrightnessSetting(); 80 mMinimumBacklight = powerManager.getMinimumScreenBrightnessSetting(); 81 UserManager userManager = context.getSystemService(UserManager.class); 82 mIsVisibleBackgroundUsersSupported = 83 userManager != null && userManager.isVisibleBackgroundUsersSupported(); 84 if (mIsVisibleBackgroundUsersSupported) { 85 mDisplayManager = context.getSystemService(DisplayManager.class); 86 } 87 } 88 89 @Override getPreferenceType()90 protected Class<SeekBarPreference> getPreferenceType() { 91 return SeekBarPreference.class; 92 } 93 94 @Override onCreateInternal()95 protected void onCreateInternal() { 96 super.onCreateInternal(); 97 setClickableWhileDisabled(getPreference(), /* clickable= */ true, p -> { 98 if (hasUserRestrictionByDpm(getContext(), DISALLOW_CONFIG_BRIGHTNESS)) { 99 showActionDisabledByAdminDialog(); 100 } else { 101 Toast.makeText(getContext(), 102 getContext().getString(R.string.action_unavailable), 103 Toast.LENGTH_LONG).show(); 104 } 105 }); 106 } 107 108 @Override onStartInternal()109 protected void onStartInternal() { 110 super.onStartInternal(); 111 getContext().getContentResolver().registerContentObserver(BRIGHTNESS_URI, 112 /* notifyForDescendants= */ false, mBrightnessObserver); 113 } 114 115 @Override onStopInternal()116 protected void onStopInternal() { 117 super.onStopInternal(); 118 getContext().getContentResolver().unregisterContentObserver(mBrightnessObserver); 119 } 120 121 @Override updateState(SeekBarPreference preference)122 protected void updateState(SeekBarPreference preference) { 123 preference.setMax(GAMMA_SPACE_MAX); 124 preference.setValue(getSeekbarValue()); 125 preference.setContinuousUpdate(true); 126 } 127 128 @Override handlePreferenceChanged(SeekBarPreference preference, Object newValue)129 protected boolean handlePreferenceChanged(SeekBarPreference preference, Object newValue) { 130 int gamma = (Integer) newValue; 131 int linear = convertGammaToLinear(gamma, mMinimumBacklight, mMaximumBacklight); 132 saveScreenBrightnessLinearValue(linear); 133 return true; 134 } 135 getSeekbarValue()136 private int getSeekbarValue() { 137 int gamma = GAMMA_SPACE_MAX; 138 try { 139 int linear = getScreenBrightnessLinearValue(); 140 gamma = convertLinearToGamma(linear, mMinimumBacklight, mMaximumBacklight); 141 } catch (Settings.SettingNotFoundException e) { 142 LOG.w("Can't find setting for SCREEN_BRIGHTNESS."); 143 } 144 return gamma; 145 } 146 147 @Override getDefaultAvailabilityStatus()148 public int getDefaultAvailabilityStatus() { 149 if (hasUserRestrictionByUm(getContext(), DISALLOW_CONFIG_BRIGHTNESS) 150 || hasUserRestrictionByDpm(getContext(), DISALLOW_CONFIG_BRIGHTNESS)) { 151 return AVAILABLE_FOR_VIEWING; 152 } 153 return AVAILABLE; 154 } 155 showActionDisabledByAdminDialog()156 private void showActionDisabledByAdminDialog() { 157 getFragmentController().showDialog( 158 EnterpriseUtils.getActionDisabledByAdminDialog(getContext(), 159 DISALLOW_CONFIG_BRIGHTNESS), 160 DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG); 161 } 162 163 @VisibleForTesting getScreenBrightnessLinearValue()164 int getScreenBrightnessLinearValue() throws Settings.SettingNotFoundException { 165 if (mIsVisibleBackgroundUsersSupported && mDisplayManager != null) { 166 float linearFloat = mDisplayManager.getBrightness(getMyOccupantZoneDisplayId()); 167 return BrightnessSynchronizer.brightnessFloatToInt(linearFloat); 168 } 169 170 return Settings.System.getIntForUser(getContext().getContentResolver(), 171 Settings.System.SCREEN_BRIGHTNESS, UserHandle.myUserId()); 172 } 173 174 @VisibleForTesting saveScreenBrightnessLinearValue(int linear)175 void saveScreenBrightnessLinearValue(int linear) { 176 if (mIsVisibleBackgroundUsersSupported) { 177 if (mDisplayManager != null) { 178 float linearFloat = BrightnessSynchronizer.brightnessIntToFloat(linear); 179 mDisplayManager.setBrightness(getMyOccupantZoneDisplayId(), linearFloat); 180 } 181 } else { 182 Settings.System.putIntForUser(getContext().getContentResolver(), 183 Settings.System.SCREEN_BRIGHTNESS, linear, UserHandle.myUserId()); 184 } 185 } 186 getMyOccupantZoneDisplayId()187 private int getMyOccupantZoneDisplayId() { 188 return ((CarSettingsApplication) getContext().getApplicationContext()) 189 .getMyOccupantZoneDisplayId(); 190 } 191 } 192