• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
4 import static android.os.Build.VERSION_CODES.P;
5 
6 import android.hardware.display.DisplayManagerGlobal;
7 import android.hardware.display.IDisplayManager;
8 import android.hardware.display.IDisplayManagerCallback;
9 import android.hardware.display.WifiDisplayStatus;
10 import android.os.RemoteException;
11 import android.view.DisplayInfo;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.TreeMap;
15 import org.robolectric.annotation.Implementation;
16 import org.robolectric.annotation.Implements;
17 import org.robolectric.annotation.Resetter;
18 import org.robolectric.shadow.api.Shadow;
19 import org.robolectric.util.ReflectionHelpers;
20 import org.robolectric.util.ReflectionHelpers.ClassParameter;
21 
22 @Implements(value = DisplayManagerGlobal.class, isInAndroidSdk = false, minSdk = JELLY_BEAN_MR1)
23 public class ShadowDisplayManagerGlobal {
24   private static DisplayManagerGlobal instance;
25 
26   private MyDisplayManager mDm;
27 
28   @Resetter
reset()29   public static void reset() {
30     instance = null;
31   }
32 
33   @Implementation
getInstance()34   synchronized public static DisplayManagerGlobal getInstance() {
35     if (instance == null) {
36       MyDisplayManager myIDisplayManager = new MyDisplayManager();
37       IDisplayManager proxy = ReflectionHelpers.createDelegatingProxy(IDisplayManager.class, myIDisplayManager);
38       instance = ReflectionHelpers.callConstructor(DisplayManagerGlobal.class,
39           ClassParameter.from(IDisplayManager.class, proxy));
40       ShadowDisplayManagerGlobal shadow = Shadow.extract(instance);
41       shadow.mDm = myIDisplayManager;
42     }
43     return instance;
44   }
45 
46   @Implementation
getWifiDisplayStatus()47   protected WifiDisplayStatus getWifiDisplayStatus() {
48     return new WifiDisplayStatus();
49   }
50 
addDisplay(DisplayInfo displayInfo)51   int addDisplay(DisplayInfo displayInfo) {
52     fixNominalDimens(displayInfo);
53 
54     return mDm.addDisplay(displayInfo);
55   }
56 
fixNominalDimens(DisplayInfo displayInfo)57   private void fixNominalDimens(DisplayInfo displayInfo) {
58     int min = Math.min(displayInfo.appWidth, displayInfo.appHeight);
59     int max = Math.max(displayInfo.appWidth, displayInfo.appHeight);
60     displayInfo.smallestNominalAppHeight = displayInfo.smallestNominalAppWidth = min;
61     displayInfo.largestNominalAppHeight = displayInfo.largestNominalAppWidth = max;
62   }
63 
changeDisplay(int displayId, DisplayInfo displayInfo)64   void changeDisplay(int displayId, DisplayInfo displayInfo) {
65     mDm.changeDisplay(displayId, displayInfo);
66   }
67 
removeDisplay(int displayId)68   void removeDisplay(int displayId) {
69     mDm.removeDisplay(displayId);
70   }
71 
72   private static class MyDisplayManager {
73     private final TreeMap<Integer, DisplayInfo> displayInfos = new TreeMap<>();
74     private int nextDisplayId = 0;
75     private final List<IDisplayManagerCallback> callbacks = new ArrayList<>();
76 
77     // @Override
getDisplayInfo(int i)78     public DisplayInfo getDisplayInfo(int i) throws RemoteException {
79       DisplayInfo displayInfo = displayInfos.get(i);
80       return displayInfo == null ? null : new DisplayInfo(displayInfo);
81     }
82 
83     // @Override // todo: use @Implements/@Implementation for signature checking
getDisplayIds()84     public int[] getDisplayIds() throws RemoteException {
85       int[] ids = new int[displayInfos.size()];
86       int i = 0;
87       for (Integer displayId : displayInfos.keySet()) {
88         ids[i++] = displayId;
89       }
90       return ids;
91     }
92 
93     // @Override
registerCallback(IDisplayManagerCallback iDisplayManagerCallback)94     public void registerCallback(IDisplayManagerCallback iDisplayManagerCallback) throws RemoteException {
95       this.callbacks.add(iDisplayManagerCallback);
96     }
97 
addDisplay(DisplayInfo displayInfo)98     synchronized private int addDisplay(DisplayInfo displayInfo) {
99       int nextId = nextDisplayId++;
100       displayInfos.put(nextId, displayInfo);
101       notifyListeners(nextId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
102       return nextId;
103     }
104 
changeDisplay(int displayId, DisplayInfo displayInfo)105     synchronized private void changeDisplay(int displayId, DisplayInfo displayInfo) {
106       if (!displayInfos.containsKey(displayId)) {
107         throw new IllegalStateException("no display " + displayId);
108       }
109 
110       displayInfos.put(displayId, displayInfo);
111       notifyListeners(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
112     }
113 
removeDisplay(int displayId)114     synchronized private void removeDisplay(int displayId) {
115       if (!displayInfos.containsKey(displayId)) {
116         throw new IllegalStateException("no display " + displayId);
117       }
118 
119       displayInfos.remove(displayId);
120       notifyListeners(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
121     }
122 
notifyListeners(int nextId, int event)123     private void notifyListeners(int nextId, int event) {
124       for (IDisplayManagerCallback callback : callbacks) {
125         try {
126           callback.onDisplayEvent(nextId, event);
127         } catch (RemoteException e) {
128           throw new RuntimeException(e);
129         }
130       }
131     }
132   }
133 }
134