1 /* 2 * Copyright (C) 2021 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 android.window; 18 19 import static android.view.Display.DEFAULT_DISPLAY; 20 21 import android.annotation.CallSuper; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.SuppressLint; 25 import android.annotation.TestApi; 26 import android.annotation.UiContext; 27 import android.app.ActivityThread; 28 import android.app.LoadedApk; 29 import android.app.Service; 30 import android.content.ComponentCallbacks; 31 import android.content.ComponentCallbacksController; 32 import android.content.Context; 33 import android.content.res.Configuration; 34 import android.hardware.display.DisplayManager; 35 import android.os.Bundle; 36 import android.os.IBinder; 37 import android.view.Display; 38 import android.view.WindowManager; 39 import android.view.WindowManager.LayoutParams.WindowType; 40 import android.view.WindowManagerImpl; 41 42 /** 43 * A {@link Service} responsible for showing a non-activity window, such as software keyboards or 44 * accessibility overlay windows. This {@link Service} has similar behavior to 45 * {@link WindowContext}, but is represented as {@link Service}. 46 * 47 * @see android.inputmethodservice.InputMethodService 48 * 49 * @hide 50 */ 51 @TestApi 52 @UiContext 53 public abstract class WindowProviderService extends Service implements WindowProvider { 54 55 private final Bundle mOptions; 56 private final WindowTokenClient mWindowToken = new WindowTokenClient(); 57 private final WindowContextController mController = new WindowContextController(mWindowToken); 58 private WindowManager mWindowManager; 59 private boolean mInitialized; 60 private final ComponentCallbacksController mCallbacksController = 61 new ComponentCallbacksController(); 62 63 /** 64 * Returns {@code true} if the {@code windowContextOptions} declares that it is a 65 * {@link WindowProviderService}. 66 * 67 * @hide 68 */ isWindowProviderService(@ullable Bundle windowContextOptions)69 public static boolean isWindowProviderService(@Nullable Bundle windowContextOptions) { 70 if (windowContextOptions == null) { 71 return false; 72 } 73 return (windowContextOptions.getBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, false)); 74 } 75 WindowProviderService()76 public WindowProviderService() { 77 mOptions = new Bundle(); 78 mOptions.putBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, true); 79 } 80 81 /** 82 * Returns the window type of this {@link WindowProviderService}. 83 * Each inheriting class must implement this method to provide the type of the window. It is 84 * used similar to {@code type} of {@link Context#createWindowContext(int, Bundle)} 85 * 86 * @see Context#createWindowContext(int, Bundle) 87 * 88 * @hide 89 */ 90 @TestApi 91 @SuppressLint("OnNameExpected") 92 // Suppress the lint because it is not a callback and users should provide window type 93 // so we cannot make it final. 94 @WindowType 95 @Override getWindowType()96 public abstract int getWindowType(); 97 98 /** 99 * Returns the option of this {@link WindowProviderService}. 100 * <p> 101 * The inheriting class can implement this method to provide the customization {@code option} of 102 * the window, but must be based on this method's returned value. 103 * It is used similar to {@code options} of {@link Context#createWindowContext(int, Bundle)} 104 * </p> 105 * <pre class="prettyprint"> 106 * public Bundle getWindowContextOptions() { 107 * final Bundle options = super.getWindowContextOptions(); 108 * options.put(KEY_ROOT_DISPLAY_AREA_ID, displayAreaInfo.rootDisplayAreaId); 109 * return options; 110 * } 111 * </pre> 112 * 113 * @hide 114 */ 115 @TestApi 116 @SuppressLint({"OnNameExpected", "NullableCollection"}) 117 // Suppress the lint because it is not a callback and users may override this API to provide 118 // launch option. Also, the return value of this API is null by default. 119 @Nullable 120 @CallSuper 121 @Override getWindowContextOptions()122 public Bundle getWindowContextOptions() { 123 return mOptions; 124 } 125 126 @SuppressLint({"OnNameExpected", "ExecutorRegistration"}) 127 // Suppress lint because this is a legacy named function and doesn't have an optional param 128 // for executor. 129 // TODO(b/259347943): Update documentation for U. 130 /** 131 * Here we override to prevent WindowProviderService from invoking 132 * {@link Application.registerComponentCallback}, which will result in callback registered 133 * for process-level Configuration change updates. 134 */ 135 @Override registerComponentCallbacks(@onNull ComponentCallbacks callback)136 public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) { 137 // For broadcasting Configuration Changes. 138 mCallbacksController.registerCallbacks(callback); 139 } 140 141 @SuppressLint("OnNameExpected") 142 @Override unregisterComponentCallbacks(@onNull ComponentCallbacks callback)143 public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) { 144 mCallbacksController.unregisterCallbacks(callback); 145 } 146 147 @SuppressLint("OnNameExpected") 148 @Override onConfigurationChanged(@onNull Configuration configuration)149 public void onConfigurationChanged(@NonNull Configuration configuration) { 150 // This is only called from WindowTokenClient. 151 mCallbacksController.dispatchConfigurationChanged(configuration); 152 } 153 154 /** 155 * Override {@link Service}'s empty implementation and listen to {@link ActivityThread} for 156 * low memory and trim memory events. 157 */ 158 @Override onLowMemory()159 public void onLowMemory() { 160 mCallbacksController.dispatchLowMemory(); 161 } 162 163 @Override onTrimMemory(int level)164 public void onTrimMemory(int level) { 165 mCallbacksController.dispatchTrimMemory(level); 166 } 167 168 /** 169 * Returns the display ID to launch this {@link WindowProviderService}. 170 * 171 * @hide 172 */ 173 @TestApi 174 @SuppressLint({"OnNameExpected"}) 175 // Suppress the lint because it is not a callback and users may override this API to provide 176 // display. 177 @NonNull getInitialDisplayId()178 public int getInitialDisplayId() { 179 return DEFAULT_DISPLAY; 180 } 181 182 /** 183 * Attaches this WindowProviderService to the {@code windowToken}. 184 * 185 * @hide 186 */ 187 @TestApi attachToWindowToken(@onNull IBinder windowToken)188 public final void attachToWindowToken(@NonNull IBinder windowToken) { 189 mController.attachToWindowToken(windowToken); 190 } 191 192 /** @hide */ 193 @Override createServiceBaseContext(ActivityThread mainThread, LoadedApk packageInfo)194 public final Context createServiceBaseContext(ActivityThread mainThread, 195 LoadedApk packageInfo) { 196 final Context context = super.createServiceBaseContext(mainThread, packageInfo); 197 final Display display = context.getSystemService(DisplayManager.class) 198 .getDisplay(getInitialDisplayId()); 199 return context.createTokenContext(mWindowToken, display); 200 } 201 202 /** @hide */ 203 @Override attachBaseContext(Context newBase)204 protected void attachBaseContext(Context newBase) { 205 super.attachBaseContext(newBase); 206 if (!mInitialized) { 207 mWindowToken.attachContext(this); 208 mController.attachToDisplayArea(getWindowType(), getDisplayId(), 209 getWindowContextOptions()); 210 mWindowManager = WindowManagerImpl.createWindowContextWindowManager(this); 211 mInitialized = true; 212 } 213 } 214 215 // Suppress the lint because ths is overridden from Context. 216 @SuppressLint("OnNameExpected") 217 @Override 218 @Nullable getSystemService(@onNull String name)219 public Object getSystemService(@NonNull String name) { 220 if (WINDOW_SERVICE.equals(name)) { 221 return mWindowManager; 222 } 223 return super.getSystemService(name); 224 } 225 226 @CallSuper 227 @Override onDestroy()228 public void onDestroy() { 229 super.onDestroy(); 230 mController.detachIfNeeded(); 231 mCallbacksController.clearCallbacks(); 232 } 233 } 234