/* * Copyright (C) 2020 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.WindowManagerImpl.createWindowContextWindowManager; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiContext; import android.content.ComponentCallbacks; import android.content.ComponentCallbacksController; import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; import android.os.Bundle; import android.view.Display; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import java.lang.ref.Reference; /** * {@link WindowContext} is a context for non-activity windows such as * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} windows or system * windows. Its resources and configuration are adjusted to the area of the display that will be * used when a new window is added via {@link android.view.WindowManager#addView}. * * @see Context#createWindowContext(int, Bundle) * @hide */ @UiContext public class WindowContext extends ContextWrapper implements WindowProvider { private final WindowManager mWindowManager; @WindowManager.LayoutParams.WindowType private final int mType; @Nullable private final Bundle mOptions; private final ComponentCallbacksController mCallbacksController = new ComponentCallbacksController(); private final WindowContextController mController; /** * Default implementation of {@link WindowContext} *
* Note that the users should call {@link Context#createWindowContext(Display, int, Bundle)} * to create a {@link WindowContext} instead of using this constructor *
* Example usage: *
* Bundle options = new Bundle();
* options.put(KEY_ROOT_DISPLAY_AREA_ID, displayAreaInfo.rootDisplayAreaId);
* Context windowContext = context.createWindowContext(display, windowType, options);
*
*
* @param base Base {@link Context} for this new instance.
* @param type Window type to be used with this context.
* @param options A bundle used to pass window-related options.
* @see DisplayAreaInfo#rootDisplayAreaId
*/
public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
super(base);
mType = type;
mOptions = options;
mWindowManager = createWindowContextWindowManager(this);
WindowTokenClient token = (WindowTokenClient) getWindowContextToken();
mController = new WindowContextController(token);
Reference.reachabilityFence(this);
}
/**
* Attaches this {@link WindowContext} to the {@link com.android.server.wm.DisplayArea}
* specified by {@code mType}, {@link #getDisplayId() display ID} and {@code mOptions}
* to receive configuration changes.
*/
public void attachToDisplayArea() {
mController.attachToDisplayArea(mType, getDisplayId(), mOptions);
}
@Override
public Object getSystemService(String name) {
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
}
return super.getSystemService(name);
}
@Override
protected void finalize() throws Throwable {
release();
super.finalize();
}
/** Used for test to invoke because we can't invoke finalize directly. */
@VisibleForTesting
public void release() {
mController.detachIfNeeded();
destroy();
}
@Override
public void destroy() {
try {
mCallbacksController.clearCallbacks();
// Called to the base ContextImpl to do final clean-up.
getBaseContext().destroy();
} finally {
Reference.reachabilityFence(this);
}
}
@Override
public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) {
mCallbacksController.registerCallbacks(callback);
}
@Override
public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) {
mCallbacksController.unregisterCallbacks(callback);
}
/** Dispatch {@link Configuration} to each {@link ComponentCallbacks}. */
@VisibleForTesting(visibility = PACKAGE)
public void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
mCallbacksController.dispatchConfigurationChanged(newConfig);
}
@Override
public int getWindowType() {
return mType;
}
@Nullable
@Override
public Bundle getWindowContextOptions() {
return mOptions;
}
}