diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 3 | ||||
| -rw-r--r-- | core/java/android/app/Service.java | 13 | ||||
| -rw-r--r-- | core/java/android/window/WindowContextController.java | 1 | ||||
| -rw-r--r-- | core/java/android/window/WindowProviderService.java | 138 |
4 files changed, 154 insertions, 1 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 35890c811428..b0235b031e03 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4385,11 +4385,12 @@ public final class ActivityThread extends ClientTransactionHandler try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); - ContextImpl context = ContextImpl.createAppContext(this, packageInfo); Application app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); + final ContextImpl context = ContextImpl.getImpl(service + .createServiceBaseContext(this, packageInfo)); // Service resources must be initialized with the same loaders as the application // context. context.getResources().addLoaders( diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 2ceea7f1a6a8..0ab3f2f4be46 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -861,6 +861,19 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac } /** + * Creates the base {@link Context} of this {@link Service}. + * Users may override this API to create customized base context. + * + * @see android.window.WindowProviderService WindowProviderService class for example + * @see ContextWrapper#attachBaseContext(Context) + * + * @hide + */ + public Context createServiceBaseContext(ActivityThread mainThread, LoadedApk packageInfo) { + return ContextImpl.createAppContext(mainThread, packageInfo); + } + + /** * @hide * Clean up any references to avoid leaks. */ diff --git a/core/java/android/window/WindowContextController.java b/core/java/android/window/WindowContextController.java index 88584f4b2571..d84f571931fd 100644 --- a/core/java/android/window/WindowContextController.java +++ b/core/java/android/window/WindowContextController.java @@ -105,6 +105,7 @@ public class WindowContextController { * a {@link com.android.server.wm.DisplayArea} by * {@link #attachToDisplayArea(int, int, Bundle)}. * + * @see WindowProviderService#attachToWindowToken(IBinder)) * @see IWindowManager#attachWindowContextToWindowToken(IBinder, IBinder) */ public void attachToWindowToken(IBinder windowToken) { diff --git a/core/java/android/window/WindowProviderService.java b/core/java/android/window/WindowProviderService.java new file mode 100644 index 000000000000..b8619fbcf334 --- /dev/null +++ b/core/java/android/window/WindowProviderService.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.window; + +import static android.view.Display.DEFAULT_DISPLAY; + +import android.annotation.CallSuper; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.annotation.TestApi; +import android.annotation.UiContext; +import android.app.ActivityThread; +import android.app.LoadedApk; +import android.app.Service; +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.Bundle; +import android.os.IBinder; +import android.view.Display; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams.WindowType; +import android.view.WindowManagerImpl; + +// TODO(b/159767464): handle #onConfigurationChanged(Configuration) +/** + * A {@link Service} responsible for showing a non-activity window, such as software keyboards or + * accessibility overlay windows. This {@link Service} has similar behavior to + * {@link WindowContext}, but is represented as {@link Service}. + * + * @see android.inputmethodservice.InputMethodService + * @see android.accessibilityservice.AccessibilityService + * + * @hide + */ +@TestApi +@UiContext +public abstract class WindowProviderService extends Service { + + private final WindowTokenClient mWindowToken = new WindowTokenClient(); + private final WindowContextController mController = new WindowContextController(mWindowToken); + private WindowManager mWindowManager; + + /** + * Returns the type of this {@link WindowProviderService}. + * Each inheriting class must implement this method to provide the type of the window. It is + * used similar to {@code type} of {@link Context#createWindowContext(int, Bundle)} + * + * @see Context#createWindowContext(int, Bundle) + * + * @hide + */ + @TestApi + @SuppressLint("OnNameExpected") + // Suppress the lint because it is not a callback and users should provide window type + // so we cannot make it final. + public abstract @WindowType int getWindowType(); + + /** + * Returns the option of this {@link WindowProviderService}. + * Default is {@code null}. The inheriting class can implement this method to provide the + * customization {@code option} of the window. It is used similar to {@code options} of + * {@link Context#createWindowContext(int, Bundle)} + * + * @see Context#createWindowContext(int, Bundle) + * + * @hide + */ + @TestApi + @SuppressLint({"OnNameExpected", "NullableCollection"}) + // Suppress the lint because it is not a callback and users may override this API to provide + // launch option. Also, the return value of this API is null by default. + @Nullable + public Bundle getWindowContextOptions() { + return null; + } + + /** + * Attaches this WindowProviderService to the {@code windowToken}. + * + * @hide + */ + @TestApi + public final void attachToWindowToken(@NonNull IBinder windowToken) { + mController.attachToWindowToken(windowToken); + } + + /** @hide */ + @Override + public final Context createServiceBaseContext(ActivityThread mainThread, + LoadedApk packageInfo) { + final Context context = super.createServiceBaseContext(mainThread, packageInfo); + // Always associate with the default display at initialization. + final Display defaultDisplay = context.getSystemService(DisplayManager.class) + .getDisplay(DEFAULT_DISPLAY); + return context.createTokenContext(mWindowToken, defaultDisplay); + } + + @CallSuper + @Override + public void onCreate() { + super.onCreate(); + mWindowToken.attachContext(this); + mController.attachToDisplayArea(getWindowType(), getDisplayId(), getWindowContextOptions()); + mWindowManager = WindowManagerImpl.createWindowContextWindowManager(this); + } + + @SuppressLint("OnNameExpected") + @Override + // Suppress the lint because ths is overridden from Context. + public @Nullable Object getSystemService(@NonNull String name) { + if (WINDOW_SERVICE.equals(name)) { + return mWindowManager; + } + return super.getSystemService(name); + } + + @CallSuper + @Override + public void onDestroy() { + super.onDestroy(); + mController.detachIfNeeded(); + } +} |
