1/*
2 * Copyright (C) 2013 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
17package android.support.v4.hardware.display;
18
19import android.content.Context;
20import android.hardware.display.DisplayManager;
21import android.os.Build;
22import android.support.annotation.RequiresApi;
23import android.view.Display;
24import android.view.WindowManager;
25
26import java.util.WeakHashMap;
27
28/**
29 * Helper for accessing features in {@link android.hardware.display.DisplayManager}
30 * in a backwards compatible fashion.
31 */
32public abstract class DisplayManagerCompat {
33    private static final WeakHashMap<Context, DisplayManagerCompat> sInstances =
34            new WeakHashMap<Context, DisplayManagerCompat>();
35
36    /**
37     * Display category: Presentation displays.
38     * <p>
39     * This category can be used to identify secondary displays that are suitable for
40     * use as presentation displays.
41     * </p>
42     *
43     * @see android.app.Presentation for information about presenting content
44     * on secondary displays.
45     * @see #getDisplays(String)
46     */
47    public static final String DISPLAY_CATEGORY_PRESENTATION =
48            "android.hardware.display.category.PRESENTATION";
49
50    DisplayManagerCompat() {
51    }
52
53    /**
54     * Gets an instance of the display manager given the context.
55     */
56    public static DisplayManagerCompat getInstance(Context context) {
57        synchronized (sInstances) {
58            DisplayManagerCompat instance = sInstances.get(context);
59            if (instance == null) {
60                if (Build.VERSION.SDK_INT >= 17) {
61                    instance = new DisplayManagerCompatApi17Impl(context);
62                } else {
63                    instance = new DisplayManagerCompatApi14Impl(context);
64                }
65                sInstances.put(context, instance);
66            }
67            return instance;
68        }
69    }
70
71    /**
72     * Gets information about a logical display.
73     *
74     * The display metrics may be adjusted to provide compatibility
75     * for legacy applications.
76     *
77     * @param displayId The logical display id.
78     * @return The display object, or null if there is no valid display with the given id.
79     */
80    public abstract Display getDisplay(int displayId);
81
82    /**
83     * Gets all currently valid logical displays.
84     *
85     * @return An array containing all displays.
86     */
87    public abstract Display[] getDisplays();
88
89    /**
90     * Gets all currently valid logical displays of the specified category.
91     * <p>
92     * When there are multiple displays in a category the returned displays are sorted
93     * of preference.  For example, if the requested category is
94     * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays
95     * then the displays are sorted so that the first display in the returned array
96     * is the most preferred presentation display.  The application may simply
97     * use the first display or allow the user to choose.
98     * </p>
99     *
100     * @param category The requested display category or null to return all displays.
101     * @return An array containing all displays sorted by order of preference.
102     *
103     * @see #DISPLAY_CATEGORY_PRESENTATION
104     */
105    public abstract Display[] getDisplays(String category);
106
107    private static class DisplayManagerCompatApi14Impl extends DisplayManagerCompat {
108        private final WindowManager mWindowManager;
109
110        DisplayManagerCompatApi14Impl(Context context) {
111            mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
112        }
113
114        @Override
115        public Display getDisplay(int displayId) {
116            Display display = mWindowManager.getDefaultDisplay();
117            if (display.getDisplayId() == displayId) {
118                return display;
119            }
120            return null;
121        }
122
123        @Override
124        public Display[] getDisplays() {
125            return new Display[] { mWindowManager.getDefaultDisplay() };
126        }
127
128        @Override
129        public Display[] getDisplays(String category) {
130            return category == null ? getDisplays() : new Display[0];
131        }
132    }
133
134    @RequiresApi(17)
135    private static class DisplayManagerCompatApi17Impl extends DisplayManagerCompat {
136        private final DisplayManager mDisplayManager;
137
138        DisplayManagerCompatApi17Impl(Context context) {
139            mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
140        }
141
142        @Override
143        public Display getDisplay(int displayId) {
144            return mDisplayManager.getDisplay(displayId);
145        }
146
147        @Override
148        public Display[] getDisplays() {
149            return mDisplayManager.getDisplays();
150        }
151
152        @Override
153        public Display[] getDisplays(String category) {
154            return mDisplayManager.getDisplays(category);
155        }
156    }
157}
158