1/*
2 * Copyright (C) 2006 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.view;
18
19import android.annotation.NonNull;
20import android.content.Context;
21import android.graphics.Region;
22import android.os.Bundle;
23import android.os.IBinder;
24import android.os.RemoteException;
25
26import com.android.internal.os.IResultReceiver;
27
28import java.util.List;
29
30/**
31 * Provides low-level communication with the system window manager for
32 * operations that are bound to a particular context, display or parent window.
33 * Instances of this object are sensitive to the compatibility info associated
34 * with the running application.
35 *
36 * This object implements the {@link ViewManager} interface,
37 * allowing you to add any View subclass as a top-level window on the screen.
38 * Additional window manager specific layout parameters are defined for
39 * control over how windows are displayed.  It also implements the {@link WindowManager}
40 * interface, allowing you to control the displays attached to the device.
41 *
42 * <p>Applications will not normally use WindowManager directly, instead relying
43 * on the higher-level facilities in {@link android.app.Activity} and
44 * {@link android.app.Dialog}.
45 *
46 * <p>Even for low-level window manager access, it is almost never correct to use
47 * this class.  For example, {@link android.app.Activity#getWindowManager}
48 * provides a window manager for adding windows that are associated with that
49 * activity -- the window manager will not normally allow you to add arbitrary
50 * windows that are not associated with an activity.
51 *
52 * @see WindowManager
53 * @see WindowManagerGlobal
54 * @hide
55 */
56public final class WindowManagerImpl implements WindowManager {
57    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
58    private final Context mContext;
59    private final Window mParentWindow;
60
61    private IBinder mDefaultToken;
62
63    public WindowManagerImpl(Context context) {
64        this(context, null);
65    }
66
67    private WindowManagerImpl(Context context, Window parentWindow) {
68        mContext = context;
69        mParentWindow = parentWindow;
70    }
71
72    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
73        return new WindowManagerImpl(mContext, parentWindow);
74    }
75
76    public WindowManagerImpl createPresentationWindowManager(Context displayContext) {
77        return new WindowManagerImpl(displayContext, mParentWindow);
78    }
79
80    /**
81     * Sets the window token to assign when none is specified by the client or
82     * available from the parent window.
83     *
84     * @param token The default token to assign.
85     */
86    public void setDefaultToken(IBinder token) {
87        mDefaultToken = token;
88    }
89
90    @Override
91    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
92        applyDefaultToken(params);
93        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
94    }
95
96    @Override
97    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
98        applyDefaultToken(params);
99        mGlobal.updateViewLayout(view, params);
100    }
101
102    private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
103        // Only use the default token if we don't have a parent window.
104        if (mDefaultToken != null && mParentWindow == null) {
105            if (!(params instanceof WindowManager.LayoutParams)) {
106                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
107            }
108
109            // Only use the default token if we don't already have a token.
110            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
111            if (wparams.token == null) {
112                wparams.token = mDefaultToken;
113            }
114        }
115    }
116
117    @Override
118    public void removeView(View view) {
119        mGlobal.removeView(view, false);
120    }
121
122    @Override
123    public void removeViewImmediate(View view) {
124        mGlobal.removeView(view, true);
125    }
126
127    @Override
128    public void requestAppKeyboardShortcuts(
129            final KeyboardShortcutsReceiver receiver, int deviceId) {
130        IResultReceiver resultReceiver = new IResultReceiver.Stub() {
131            @Override
132            public void send(int resultCode, Bundle resultData) throws RemoteException {
133                List<KeyboardShortcutGroup> result =
134                        resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY);
135                receiver.onKeyboardShortcutsReceived(result);
136            }
137        };
138        try {
139            WindowManagerGlobal.getWindowManagerService()
140                .requestAppKeyboardShortcuts(resultReceiver, deviceId);
141        } catch (RemoteException e) {
142        }
143    }
144
145    @Override
146    public Display getDefaultDisplay() {
147        return mContext.getDisplay();
148    }
149
150    @Override
151    public Region getCurrentImeTouchRegion() {
152        try {
153            return WindowManagerGlobal.getWindowManagerService().getCurrentImeTouchRegion();
154        } catch (RemoteException e) {
155        }
156        return null;
157    }
158}
159