1 /*
2  * Copyright (C) 2022 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 android.content.Context;
20 import android.graphics.Point;
21 import android.hardware.display.DisplayManager;
22 import android.util.Log;
23 import android.view.Display;
24 
25 import androidx.annotation.VisibleForTesting;
26 
27 import com.android.settings.R;
28 import com.android.settings.core.BasePreferenceController;
29 
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Set;
35 
36 /** Controller that switch the screen resolution. */
37 public class ScreenResolutionController extends BasePreferenceController {
38     private static final String TAG = "ScreenResolutionController";
39     static final int HIGHRESOLUTION_IDX = 0;
40     static final int FULLRESOLUTION_IDX = 1;
41 
42     private Display mDisplay;
43     private Set<Point> mSupportedResolutions = null;
44     private int mHighWidth = 0;
45     private int mFullWidth = 0;
46     private int mHighHeight = 0;
47     private int mFullHeight = 0;
48 
ScreenResolutionController(Context context, String key)49     public ScreenResolutionController(Context context, String key) {
50         super(context, key);
51 
52         mDisplay =
53                 mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY);
54 
55         initSupportedResolutionData();
56     }
57 
58     /**
59      * Initialize the resolution data. So far, we support two resolution switching. Save the width
60      * and the height for high resolution and full resolution.
61      */
initSupportedResolutionData()62     private void initSupportedResolutionData() {
63         // Collect and filter the resolutions
64         Set<Point> resolutions = new HashSet<>();
65         for (Display.Mode mode : getSupportedModes()) {
66             resolutions.add(new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight()));
67         }
68         mSupportedResolutions = resolutions;
69 
70         // Get the width and height for high resolution and full resolution
71         List<Point> resolutionList = new ArrayList<>(resolutions);
72         if (resolutionList == null || resolutionList.size() != 2) {
73             Log.e(TAG, "No support");
74             return;
75         }
76 
77         Collections.sort(resolutionList, (p1, p2) -> p1.x * p1.y - p2.x * p2.y);
78         mHighWidth = resolutionList.get(HIGHRESOLUTION_IDX).x;
79         mHighHeight = resolutionList.get(HIGHRESOLUTION_IDX).y;
80         mFullWidth = resolutionList.get(FULLRESOLUTION_IDX).x;
81         mFullHeight = resolutionList.get(FULLRESOLUTION_IDX).y;
82     }
83 
84     /** Return true if the device contains two (or more) resolutions. */
checkSupportedResolutions()85     protected boolean checkSupportedResolutions() {
86         return getHighWidth() != 0 && getFullWidth() != 0;
87     }
88 
89     @Override
getAvailabilityStatus()90     public int getAvailabilityStatus() {
91         return (checkSupportedResolutions()) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
92     }
93 
94     @Override
getSummary()95     public CharSequence getSummary() {
96         String summary = null;
97         int width = getDisplayWidth();
98         if (width == mHighWidth) {
99             summary = mContext.getString(R.string.screen_resolution_option_high);
100         } else if (width == mFullWidth) {
101             summary = mContext.getString(R.string.screen_resolution_option_full);
102         } else {
103             summary = mContext.getString(R.string.screen_resolution_title);
104         }
105 
106         return summary;
107     }
108 
109     /** Return all supported resolutions of the device. */
getAllSupportedResolutions()110     public Set<Point> getAllSupportedResolutions() {
111         return this.mSupportedResolutions;
112     }
113 
114     /** Return the high resolution width of the device. */
getHighWidth()115     public int getHighWidth() {
116         return this.mHighWidth;
117     }
118 
119     /** Return the full resolution width of the device. */
getFullWidth()120     public int getFullWidth() {
121         return this.mFullWidth;
122     }
123 
124     /** Return the high resolution height of the device. */
getHighHeight()125     public int getHighHeight() {
126         return this.mHighHeight;
127     }
128 
129     /** Return the full resolution height of the device. */
getFullHeight()130     public int getFullHeight() {
131         return this.mFullHeight;
132     }
133 
134     @VisibleForTesting
getDisplayWidth()135     public int getDisplayWidth() {
136         return mDisplay.getMode().getPhysicalWidth();
137     }
138 
139     @VisibleForTesting
getSupportedModes()140     public Display.Mode[] getSupportedModes() {
141         return mDisplay.getSupportedModes();
142     }
143 }
144