1 /*
2  * 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 
17 package com.android.settings.display;
18 
19 import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_HIGH;
20 import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_MEDIUM;
21 import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_STANDARD;
22 import static android.app.UiModeManager.ContrastUtils.fromContrastLevel;
23 import static android.app.UiModeManager.ContrastUtils.toContrastLevel;
24 
25 import android.app.UiModeManager;
26 import android.content.Context;
27 import android.provider.Settings;
28 import android.view.View;
29 import android.widget.LinearLayout;
30 
31 import androidx.annotation.NonNull;
32 import androidx.annotation.Nullable;
33 import androidx.preference.PreferenceScreen;
34 
35 import com.android.settings.R;
36 import com.android.settings.core.BasePreferenceController;
37 import com.android.settingslib.core.lifecycle.LifecycleObserver;
38 import com.android.settingslib.core.lifecycle.events.OnStart;
39 import com.android.settingslib.core.lifecycle.events.OnStop;
40 import com.android.settingslib.widget.LayoutPreference;
41 
42 import java.util.HashMap;
43 import java.util.Map;
44 import java.util.concurrent.Executor;
45 
46 /**
47  * Controller for contrast selector.
48  */
49 public class ContrastSelectorPreferenceController extends BasePreferenceController
50         implements LifecycleObserver, OnStart, OnStop, UiModeManager.ContrastChangeListener {
51 
52     private static final String KEY_COLOR_CONTRAST_SELECTOR = "color_contrast_selector";
53 
54     private final Executor mMainExecutor;
55     private final UiModeManager mUiModeManager;
56     private Map<Integer, LinearLayout> mContrastButtons = new HashMap<>();
57 
ContrastSelectorPreferenceController(@onNull Context context, @NonNull String preferenceKey)58     public ContrastSelectorPreferenceController(@NonNull Context context,
59             @NonNull String preferenceKey) {
60         super(context, preferenceKey);
61 
62         mMainExecutor = mContext.getMainExecutor();
63         mUiModeManager = mContext.getSystemService(UiModeManager.class);
64     }
65 
66     @Override
displayPreference(@onNull PreferenceScreen screen)67     public void displayPreference(@NonNull PreferenceScreen screen) {
68         super.displayPreference(screen);
69 
70         final LayoutPreference mLayoutPreference =
71                 screen.findPreference(KEY_COLOR_CONTRAST_SELECTOR);
72 
73         mContrastButtons = Map.ofEntries(
74                 Map.entry(CONTRAST_LEVEL_STANDARD,
75                         mLayoutPreference.findViewById(R.id.contrast_button_default)),
76                 Map.entry(CONTRAST_LEVEL_MEDIUM,
77                         mLayoutPreference.findViewById(R.id.contrast_button_medium)),
78                 Map.entry(CONTRAST_LEVEL_HIGH,
79                         mLayoutPreference.findViewById(R.id.contrast_button_high))
80         );
81 
82         mContrastButtons.forEach((contrastLevel, contrastButton) -> {
83             contrastButton.setOnClickListener(new View.OnClickListener() {
84                 @Override
85                 public void onClick(@Nullable View v) {
86                     Settings.Secure.putFloat(mContext.getContentResolver(),
87                             Settings.Secure.CONTRAST_LEVEL,
88                             fromContrastLevel(contrastLevel));
89                 }
90             });
91         });
92 
93         highlightContrast(toContrastLevel(mUiModeManager.getContrast()));
94     }
95 
96     @Override
getAvailabilityStatus()97     public int getAvailabilityStatus() {
98         // The main preferences screen is feature guarded, so this always returns AVAILABLE.
99         return AVAILABLE;
100     }
101 
102     @Override
onStart()103     public void onStart() {
104         mUiModeManager.addContrastChangeListener(mMainExecutor, this);
105     }
106 
107     @Override
onStop()108     public void onStop() {
109         mUiModeManager.removeContrastChangeListener(this);
110     }
111 
112     @Override
onContrastChanged(float contrast)113     public void onContrastChanged(float contrast) {
114         highlightContrast(toContrastLevel(contrast));
115     }
116 
highlightContrast(int contrast)117     private void highlightContrast(int contrast) {
118         mContrastButtons.forEach((level, button) -> {
119             button.setSelected(level == contrast);
120         });
121     }
122 }
123