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