1 /*
<lambda>null2  * Copyright (C) 2024 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 package com.android.settings.display
17 
18 import android.app.ActivityOptions
19 import android.content.Context
20 import android.content.Intent
21 import android.content.Intent.ACTION_SHOW_BRIGHTNESS_DIALOG
22 import android.content.Intent.EXTRA_BRIGHTNESS_DIALOG_IS_FULL_WIDTH
23 import android.hardware.display.BrightnessInfo
24 import android.hardware.display.DisplayManager
25 import android.hardware.display.DisplayManager.DisplayListener
26 import android.os.UserManager
27 import android.provider.Settings.System
28 import androidx.preference.Preference
29 import com.android.settings.PreferenceRestrictionMixin
30 import com.android.settings.R
31 import com.android.settings.Utils
32 import com.android.settings.core.SettingsBaseActivity
33 import com.android.settingslib.RestrictedPreference
34 import com.android.settingslib.datastore.HandlerExecutor
35 import com.android.settingslib.datastore.KeyedObserver
36 import com.android.settingslib.datastore.SettingsSystemStore
37 import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX
38 import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN
39 import com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat
40 import com.android.settingslib.metadata.PreferenceLifecycleContext
41 import com.android.settingslib.metadata.PreferenceLifecycleProvider
42 import com.android.settingslib.metadata.PreferenceMetadata
43 import com.android.settingslib.metadata.PreferenceSummaryProvider
44 import com.android.settingslib.preference.PreferenceBinding
45 import com.android.settingslib.transition.SettingsTransitionHelper
46 import java.text.NumberFormat
47 
48 // LINT.IfChange
49 class BrightnessLevelPreference :
50     PreferenceMetadata,
51     PreferenceBinding,
52     PreferenceRestrictionMixin,
53     PreferenceSummaryProvider,
54     PreferenceLifecycleProvider,
55     Preference.OnPreferenceClickListener {
56 
57     private var brightnessObserver: KeyedObserver<String>? = null
58     private var displayListener: DisplayListener? = null
59 
60     override val key: String
61         get() = KEY
62 
63     override val title: Int
64         get() = R.string.brightness
65 
66     override val keywords: Int
67         get() = R.string.keywords_display_brightness_level
68 
69     override fun getSummary(context: Context): CharSequence? =
70         NumberFormat.getPercentInstance().format(getCurrentBrightness(context))
71 
72     override fun isEnabled(context: Context) = super<PreferenceRestrictionMixin>.isEnabled(context)
73 
74     override val restrictionKeys
75         get() = arrayOf(UserManager.DISALLOW_CONFIG_BRIGHTNESS)
76 
77     override val useAdminDisabledSummary: Boolean
78         get() = true
79 
80     override fun createWidget(context: Context) = RestrictedPreference(context)
81 
82     override fun bind(preference: Preference, metadata: PreferenceMetadata) {
83         super.bind(preference, metadata)
84         preference.onPreferenceClickListener = this
85     }
86 
87     override fun onStart(context: PreferenceLifecycleContext) {
88         val observer = KeyedObserver<String> { _, _ -> context.notifyPreferenceChange(KEY) }
89         brightnessObserver = observer
90         SettingsSystemStore.get(context)
91             .addObserver(System.SCREEN_AUTO_BRIGHTNESS_ADJ, observer, HandlerExecutor.main)
92 
93         val listener =
94             object : DisplayListener {
95                 override fun onDisplayAdded(displayId: Int) {}
96 
97                 override fun onDisplayRemoved(displayId: Int) {}
98 
99                 override fun onDisplayChanged(displayId: Int) {
100                     context.notifyPreferenceChange(KEY)
101                 }
102             }
103         displayListener = listener
104         context.displayManager.registerDisplayListener(
105             listener,
106             HandlerExecutor.main,
107             /* eventFlags= */ 0,
108             DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
109         )
110     }
111 
112     override fun onStop(context: PreferenceLifecycleContext) {
113         brightnessObserver?.let {
114             SettingsSystemStore.get(context).removeObserver(System.SCREEN_AUTO_BRIGHTNESS_ADJ, it)
115             brightnessObserver = null
116         }
117 
118         displayListener?.let {
119             context.displayManager.unregisterDisplayListener(it)
120             displayListener = null
121         }
122     }
123 
124     private val Context.displayManager: DisplayManager
125         get() = getSystemService(DisplayManager::class.java)!!
126 
127     override fun onPreferenceClick(preference: Preference): Boolean {
128         val context = preference.context
129         val intent =
130             Intent(ACTION_SHOW_BRIGHTNESS_DIALOG)
131                 .setPackage(Utils.SYSTEMUI_PACKAGE_NAME)
132                 .putExtra(
133                     SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
134                     SettingsTransitionHelper.TransitionType.TRANSITION_NONE,
135                 )
136                 .putExtra(EXTRA_BRIGHTNESS_DIALOG_IS_FULL_WIDTH, true)
137         val options =
138             ActivityOptions.makeCustomAnimation(
139                 context,
140                 android.R.anim.fade_in,
141                 android.R.anim.fade_out,
142             )
143         context.startActivityForResult(preference.key, intent, 0, options.toBundle())
144         return true
145     }
146 
147     private fun getCurrentBrightness(context: Context): Double {
148         val info: BrightnessInfo? = context.display.brightnessInfo
149         val value =
150             info?.run {
151                 convertLinearToGammaFloat(brightness, brightnessMinimum, brightnessMaximum)
152             }
153         return getPercentage(value?.toDouble() ?: 0.0)
154     }
155 
156     private fun getPercentage(value: Double): Double =
157         when {
158             value > GAMMA_SPACE_MAX -> 1.0
159             value < GAMMA_SPACE_MIN -> 0.0
160             else -> (value - GAMMA_SPACE_MIN) / (GAMMA_SPACE_MAX - GAMMA_SPACE_MIN)
161         }
162 
163     companion object {
164         const val KEY = "brightness"
165     }
166 }
167 // LINT.ThenChange(BrightnessLevelPreferenceController.java)
168