1 /*
2  * Copyright (C) 2019 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.server.wm;
18 
19 import android.content.res.Configuration;
20 import android.graphics.Rect;
21 import android.os.RemoteCallbackList;
22 import android.os.RemoteException;
23 import android.util.IntArray;
24 import android.view.IDisplayWindowListener;
25 
26 import java.util.ArrayList;
27 import java.util.Set;
28 
29 /**
30  * Manages dispatch of relevant hierarchy changes to interested listeners. Listeners are assumed
31  * to be remote.
32  */
33 class DisplayWindowListenerController {
34     RemoteCallbackList<IDisplayWindowListener> mDisplayListeners = new RemoteCallbackList<>();
35 
36     private final WindowManagerService mService;
37 
DisplayWindowListenerController(WindowManagerService service)38     DisplayWindowListenerController(WindowManagerService service) {
39         mService = service;
40     }
41 
registerListener(IDisplayWindowListener listener)42     int[] registerListener(IDisplayWindowListener listener) {
43         synchronized (mService.mGlobalLock) {
44             mDisplayListeners.register(listener);
45             final IntArray displayIds = new IntArray();
46             mService.mAtmService.mRootWindowContainer.forAllDisplays((displayContent) -> {
47                 displayIds.add(displayContent.mDisplayId);
48             });
49             return displayIds.toArray();
50         }
51     }
52 
unregisterListener(IDisplayWindowListener listener)53     void unregisterListener(IDisplayWindowListener listener) {
54         mDisplayListeners.unregister(listener);
55     }
56 
dispatchDisplayAdded(DisplayContent display)57     void dispatchDisplayAdded(DisplayContent display) {
58         int count = mDisplayListeners.beginBroadcast();
59         for (int i = 0; i < count; ++i) {
60             try {
61                 mDisplayListeners.getBroadcastItem(i).onDisplayAdded(display.mDisplayId);
62             } catch (RemoteException e) {
63             }
64         }
65         mDisplayListeners.finishBroadcast();
66     }
67 
dispatchDisplayChanged(DisplayContent display, Configuration newConfig)68     void dispatchDisplayChanged(DisplayContent display, Configuration newConfig) {
69         // Only report changed if this has actually been added to the hierarchy already.
70         boolean isInHierarchy = false;
71         for (int i = 0; i < display.getParent().getChildCount(); ++i) {
72             if (display.getParent().getChildAt(i) == display) {
73                 isInHierarchy = true;
74             }
75         }
76         if (!isInHierarchy) {
77             return;
78         }
79         int count = mDisplayListeners.beginBroadcast();
80         for (int i = 0; i < count; ++i) {
81             try {
82                 mDisplayListeners.getBroadcastItem(i).onDisplayConfigurationChanged(
83                         display.getDisplayId(), newConfig);
84             } catch (RemoteException e) {
85             }
86         }
87         mDisplayListeners.finishBroadcast();
88     }
89 
dispatchDisplayRemoved(DisplayContent display)90     void dispatchDisplayRemoved(DisplayContent display) {
91         int count = mDisplayListeners.beginBroadcast();
92         for (int i = 0; i < count; ++i) {
93             try {
94                 mDisplayListeners.getBroadcastItem(i).onDisplayRemoved(display.mDisplayId);
95             } catch (RemoteException e) {
96             }
97         }
98         mDisplayListeners.finishBroadcast();
99     }
100 
dispatchFixedRotationStarted(DisplayContent display, int newRotation)101     void dispatchFixedRotationStarted(DisplayContent display, int newRotation) {
102         int count = mDisplayListeners.beginBroadcast();
103         for (int i = 0; i < count; ++i) {
104             try {
105                 mDisplayListeners.getBroadcastItem(i).onFixedRotationStarted(
106                         display.mDisplayId, newRotation);
107             } catch (RemoteException e) {
108             }
109         }
110         mDisplayListeners.finishBroadcast();
111     }
112 
dispatchFixedRotationFinished(DisplayContent display)113     void dispatchFixedRotationFinished(DisplayContent display) {
114         int count = mDisplayListeners.beginBroadcast();
115         for (int i = 0; i < count; ++i) {
116             try {
117                 mDisplayListeners.getBroadcastItem(i).onFixedRotationFinished(display.mDisplayId);
118             } catch (RemoteException e) {
119             }
120         }
121         mDisplayListeners.finishBroadcast();
122     }
123 
dispatchKeepClearAreasChanged(DisplayContent display, Set<Rect> restricted, Set<Rect> unrestricted)124     void dispatchKeepClearAreasChanged(DisplayContent display, Set<Rect> restricted,
125             Set<Rect> unrestricted) {
126         int count = mDisplayListeners.beginBroadcast();
127         for (int i = 0; i < count; ++i) {
128             try {
129                 mDisplayListeners.getBroadcastItem(i).onKeepClearAreasChanged(display.mDisplayId,
130                         new ArrayList<>(restricted), new ArrayList<>(unrestricted));
131             } catch (RemoteException e) {
132             }
133         }
134         mDisplayListeners.finishBroadcast();
135     }
136 }
137