Merge "Enable to listen to WindowContext's config changes" into sc-dev
This commit is contained in:
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
|
|||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.content.ComponentCallbacks;
|
import android.content.ComponentCallbacks;
|
||||||
import android.content.ComponentCallbacks2;
|
import android.content.ComponentCallbacks2;
|
||||||
|
import android.content.ComponentCallbacksController;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -53,14 +54,14 @@ import java.util.ArrayList;
|
|||||||
public class Application extends ContextWrapper implements ComponentCallbacks2 {
|
public class Application extends ContextWrapper implements ComponentCallbacks2 {
|
||||||
private static final String TAG = "Application";
|
private static final String TAG = "Application";
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private ArrayList<ComponentCallbacks> mComponentCallbacks =
|
|
||||||
new ArrayList<ComponentCallbacks>();
|
|
||||||
@UnsupportedAppUsage
|
|
||||||
private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
|
private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
|
||||||
new ArrayList<ActivityLifecycleCallbacks>();
|
new ArrayList<ActivityLifecycleCallbacks>();
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
|
private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
|
||||||
|
|
||||||
|
private final ComponentCallbacksController mCallbacksController =
|
||||||
|
new ComponentCallbacksController();
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public LoadedApk mLoadedApk;
|
public LoadedApk mLoadedApk;
|
||||||
@@ -260,47 +261,25 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
|
|||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||||
Object[] callbacks = collectComponentCallbacks();
|
mCallbacksController.dispatchConfigurationChanged(newConfig);
|
||||||
if (callbacks != null) {
|
|
||||||
for (int i=0; i<callbacks.length; i++) {
|
|
||||||
((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void onLowMemory() {
|
public void onLowMemory() {
|
||||||
Object[] callbacks = collectComponentCallbacks();
|
mCallbacksController.dispatchLowMemory();
|
||||||
if (callbacks != null) {
|
|
||||||
for (int i=0; i<callbacks.length; i++) {
|
|
||||||
((ComponentCallbacks)callbacks[i]).onLowMemory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void onTrimMemory(int level) {
|
public void onTrimMemory(int level) {
|
||||||
Object[] callbacks = collectComponentCallbacks();
|
mCallbacksController.dispatchTrimMemory(level);
|
||||||
if (callbacks != null) {
|
|
||||||
for (int i=0; i<callbacks.length; i++) {
|
|
||||||
Object c = callbacks[i];
|
|
||||||
if (c instanceof ComponentCallbacks2) {
|
|
||||||
((ComponentCallbacks2)c).onTrimMemory(level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerComponentCallbacks(ComponentCallbacks callback) {
|
public void registerComponentCallbacks(ComponentCallbacks callback) {
|
||||||
synchronized (mComponentCallbacks) {
|
mCallbacksController.registerCallbacks(callback);
|
||||||
mComponentCallbacks.add(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterComponentCallbacks(ComponentCallbacks callback) {
|
public void unregisterComponentCallbacks(ComponentCallbacks callback) {
|
||||||
synchronized (mComponentCallbacks) {
|
mCallbacksController.unregisterCallbacks(callback);
|
||||||
mComponentCallbacks.remove(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
|
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
|
||||||
@@ -575,16 +554,6 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object[] collectComponentCallbacks() {
|
|
||||||
Object[] callbacks = null;
|
|
||||||
synchronized (mComponentCallbacks) {
|
|
||||||
if (mComponentCallbacks.size() > 0) {
|
|
||||||
callbacks = mComponentCallbacks.toArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return callbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private Object[] collectActivityLifecycleCallbacks() {
|
private Object[] collectActivityLifecycleCallbacks() {
|
||||||
Object[] callbacks = null;
|
Object[] callbacks = null;
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ import static android.view.WindowManagerImpl.createWindowContextWindowManager;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.UiContext;
|
import android.annotation.UiContext;
|
||||||
|
import android.content.ComponentCallbacks;
|
||||||
|
import android.content.ComponentCallbacksController;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -49,6 +52,8 @@ public class WindowContext extends ContextWrapper {
|
|||||||
private final IWindowManager mWms;
|
private final IWindowManager mWms;
|
||||||
private final WindowTokenClient mToken;
|
private final WindowTokenClient mToken;
|
||||||
private boolean mListenerRegistered;
|
private boolean mListenerRegistered;
|
||||||
|
private final ComponentCallbacksController mCallbacksController =
|
||||||
|
new ComponentCallbacksController();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
|
* Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
|
||||||
@@ -131,8 +136,24 @@ public class WindowContext extends ContextWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void destroy() {
|
void destroy() {
|
||||||
|
mCallbacksController.clearCallbacks();
|
||||||
final ContextImpl impl = (ContextImpl) getBaseContext();
|
final ContextImpl impl = (ContextImpl) getBaseContext();
|
||||||
impl.scheduleFinalCleanup(getClass().getName(), "WindowContext");
|
impl.scheduleFinalCleanup(getClass().getName(), "WindowContext");
|
||||||
Reference.reachabilityFence(this);
|
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}. */
|
||||||
|
void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
|
||||||
|
mCallbacksController.dispatchConfigurationChanged(newConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class WindowTokenClient extends IWindowToken.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration newConfig, int newDisplayId) {
|
public void onConfigurationChanged(Configuration newConfig, int newDisplayId) {
|
||||||
final Context context = mContextRef.get();
|
final WindowContext context = mContextRef.get();
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,8 @@ public class WindowTokenClient extends IWindowToken.Stub {
|
|||||||
if (displayChanged || configChanged) {
|
if (displayChanged || configChanged) {
|
||||||
// TODO(ag/9789103): update resource manager logic to track non-activity tokens
|
// TODO(ag/9789103): update resource manager logic to track non-activity tokens
|
||||||
mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId);
|
mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId);
|
||||||
|
ActivityThread.currentActivityThread().getHandler().post(
|
||||||
|
() -> context.dispatchConfigurationChanged(newConfig));
|
||||||
}
|
}
|
||||||
if (displayChanged) {
|
if (displayChanged) {
|
||||||
context.updateDisplay(newDisplayId);
|
context.updateDisplay(newDisplayId);
|
||||||
|
|||||||
127
core/java/android/content/ComponentCallbacksController.java
Normal file
127
core/java/android/content/ComponentCallbacksController.java
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* 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.content;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class to manage {@link ComponentCallbacks} and {@link ComponentCallbacks2}, such as
|
||||||
|
* registering ,unregistering {@link ComponentCallbacks} and sending callbacks to all registered
|
||||||
|
* {@link ComponentCallbacks}.
|
||||||
|
*
|
||||||
|
* @see Context#registerComponentCallbacks(ComponentCallbacks)
|
||||||
|
* @see Context#unregisterComponentCallbacks(ComponentCallbacks)
|
||||||
|
* @see ComponentCallbacks
|
||||||
|
* @see ComponentCallbacks2
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class ComponentCallbacksController {
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private List<ComponentCallbacks> mComponentCallbacks;
|
||||||
|
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the {@link ComponentCallbacks}.
|
||||||
|
*
|
||||||
|
* @see Context#registerComponentCallbacks(ComponentCallbacks)
|
||||||
|
*/
|
||||||
|
public void registerCallbacks(@NonNull ComponentCallbacks callbacks) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mComponentCallbacks == null) {
|
||||||
|
mComponentCallbacks = new ArrayList<>();
|
||||||
|
}
|
||||||
|
mComponentCallbacks.add(callbacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister the {@link ComponentCallbacks}.
|
||||||
|
*
|
||||||
|
* @see Context#unregisterComponentCallbacks(ComponentCallbacks)
|
||||||
|
*/
|
||||||
|
public void unregisterCallbacks(@NonNull ComponentCallbacks callbacks) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mComponentCallbacks == null || mComponentCallbacks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mComponentCallbacks.remove(callbacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all registered {@link ComponentCallbacks}.
|
||||||
|
* It is useful when the associated {@link Context} is going to be released.
|
||||||
|
*/
|
||||||
|
public void clearCallbacks() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mComponentCallbacks != null) {
|
||||||
|
mComponentCallbacks.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sending {@link ComponentCallbacks#onConfigurationChanged(Configuration)} to all registered
|
||||||
|
* {@link ComponentCallbacks}.
|
||||||
|
*/
|
||||||
|
public void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
|
||||||
|
forAllComponentCallbacks(callbacks -> callbacks.onConfigurationChanged(newConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sending {@link ComponentCallbacks#onLowMemory()} to all registered
|
||||||
|
* {@link ComponentCallbacks}.
|
||||||
|
*/
|
||||||
|
public void dispatchLowMemory() {
|
||||||
|
forAllComponentCallbacks(ComponentCallbacks::onLowMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sending {@link ComponentCallbacks2#onTrimMemory(int)} to all registered
|
||||||
|
* {@link ComponentCallbacks2}.
|
||||||
|
*/
|
||||||
|
public void dispatchTrimMemory(int level) {
|
||||||
|
forAllComponentCallbacks(callbacks -> {
|
||||||
|
if (callbacks instanceof ComponentCallbacks2) {
|
||||||
|
((ComponentCallbacks2) callbacks).onTrimMemory(level);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void forAllComponentCallbacks(Consumer<ComponentCallbacks> callbacksConsumer) {
|
||||||
|
final ComponentCallbacks[] callbacksArray;
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mComponentCallbacks == null || mComponentCallbacks.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callbacksArray = new ComponentCallbacks[mComponentCallbacks.size()];
|
||||||
|
mComponentCallbacks.toArray(callbacksArray);
|
||||||
|
}
|
||||||
|
for (ComponentCallbacks callbacks : callbacksArray) {
|
||||||
|
callbacksConsumer.accept(callbacks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -655,12 +655,21 @@ public abstract class Context {
|
|||||||
/**
|
/**
|
||||||
* Add a new {@link ComponentCallbacks} to the base application of the
|
* Add a new {@link ComponentCallbacks} to the base application of the
|
||||||
* Context, which will be called at the same times as the ComponentCallbacks
|
* Context, which will be called at the same times as the ComponentCallbacks
|
||||||
* methods of activities and other components are called. Note that you
|
* methods of activities and other components are called. Note that you
|
||||||
* <em>must</em> be sure to use {@link #unregisterComponentCallbacks} when
|
* <em>must</em> be sure to use {@link #unregisterComponentCallbacks} when
|
||||||
* appropriate in the future; this will not be removed for you.
|
* appropriate in the future; this will not be removed for you.
|
||||||
|
* <p>
|
||||||
|
* After {@link Build.VERSION_CODES#S}, Registering the ComponentCallbacks to Context created
|
||||||
|
* via {@link #createWindowContext(int, Bundle)} or
|
||||||
|
* {@link #createWindowContext(Display, int, Bundle)} will receive
|
||||||
|
* {@link ComponentCallbacks#onConfigurationChanged(Configuration)} from Window Context rather
|
||||||
|
* than its base application. It is helpful if you want to handle UI components that
|
||||||
|
* associated with the Window Context when the Window Context has configuration changes.</p>
|
||||||
*
|
*
|
||||||
* @param callback The interface to call. This can be either a
|
* @param callback The interface to call. This can be either a
|
||||||
* {@link ComponentCallbacks} or {@link ComponentCallbacks2} interface.
|
* {@link ComponentCallbacks} or {@link ComponentCallbacks2} interface.
|
||||||
|
*
|
||||||
|
* @see Context#createWindowContext(int, Bundle)
|
||||||
*/
|
*/
|
||||||
public void registerComponentCallbacks(ComponentCallbacks callback) {
|
public void registerComponentCallbacks(ComponentCallbacks callback) {
|
||||||
getApplicationContext().registerComponentCallbacks(callback);
|
getApplicationContext().registerComponentCallbacks(callback);
|
||||||
@@ -6358,6 +6367,16 @@ public abstract class Context {
|
|||||||
* windowContext.getSystemService(WindowManager.class).addView(overlayView, mParams);
|
* windowContext.getSystemService(WindowManager.class).addView(overlayView, mParams);
|
||||||
* </pre>
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
|
* After {@link Build.VERSION_CODES#S}, window context provides the capability to listen to its
|
||||||
|
* {@link Configuration} changes by calling
|
||||||
|
* {@link #registerComponentCallbacks(ComponentCallbacks)}, while other kinds of {@link Context}
|
||||||
|
* will register the {@link ComponentCallbacks} to {@link #getApplicationContext() its
|
||||||
|
* Application context}. Note that window context only propagate
|
||||||
|
* {@link ComponentCallbacks#onConfigurationChanged(Configuration)} callback.
|
||||||
|
* {@link ComponentCallbacks#onLowMemory()} or other callbacks in {@link ComponentCallbacks2}
|
||||||
|
* won't be invoked.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
* Note that using {@link android.app.Application} or {@link android.app.Service} context for
|
* Note that using {@link android.app.Application} or {@link android.app.Service} context for
|
||||||
* UI-related queries may result in layout or continuity issues on devices with variable screen
|
* UI-related queries may result in layout or continuity issues on devices with variable screen
|
||||||
* sizes (e.g. foldables) or in multi-window modes, since these non-UI contexts may not reflect
|
* sizes (e.g. foldables) or in multi-window modes, since these non-UI contexts may not reflect
|
||||||
|
|||||||
@@ -44,9 +44,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include-filter": "android.content.ContextTest"
|
"include-filter": "android.content.ContextTest"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include-filter": "android.content.ComponentCallbacksControllerTest"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java"]
|
"file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java", "(/|^)ComponentCallbacksController.java"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.content;
|
||||||
|
|
||||||
|
import static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.app.WindowConfiguration;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest FrameworksCoreTests:ComponentCallbacksControllerTest
|
||||||
|
*/
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ComponentCallbacksControllerTest {
|
||||||
|
private ComponentCallbacksController mController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mController = new ComponentCallbacksController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnregisterCallbackWithoutRegistrationNoCrash() {
|
||||||
|
mController.unregisterCallbacks(new FakeComponentCallbacks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDispatchWithEmptyCallbacksNoCrash() {
|
||||||
|
mController.dispatchConfigurationChanged(new Configuration());
|
||||||
|
mController.dispatchLowMemory();
|
||||||
|
mController.dispatchTrimMemory(TRIM_MEMORY_BACKGROUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClearCallbacksNoCrash() {
|
||||||
|
mController.clearCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDispatchTrimMemoryWithoutComponentCallbacks2NoCrash() {
|
||||||
|
// Register a ComponentCallbacks instead of ComponentCallbacks2
|
||||||
|
mController.registerCallbacks(new FakeComponentCallbacks());
|
||||||
|
|
||||||
|
mController.dispatchTrimMemory(TRIM_MEMORY_BACKGROUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDispatchConfigurationChanged() throws Exception {
|
||||||
|
final TestComponentCallbacks2 callback = new TestComponentCallbacks2();
|
||||||
|
mController.registerCallbacks(callback);
|
||||||
|
|
||||||
|
final Configuration config = new Configuration();
|
||||||
|
config.windowConfiguration.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
|
||||||
|
config.windowConfiguration.setBounds(new Rect(0, 0, 100, 100));
|
||||||
|
|
||||||
|
mController.dispatchConfigurationChanged(config);
|
||||||
|
|
||||||
|
assertThat(callback.mConfiguration).isEqualTo(config);
|
||||||
|
|
||||||
|
mController.dispatchConfigurationChanged(Configuration.EMPTY);
|
||||||
|
|
||||||
|
assertThat(callback.mConfiguration).isEqualTo(Configuration.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDispatchLowMemory() {
|
||||||
|
final TestComponentCallbacks2 callback = new TestComponentCallbacks2();
|
||||||
|
mController.registerCallbacks(callback);
|
||||||
|
|
||||||
|
mController.dispatchLowMemory();
|
||||||
|
|
||||||
|
assertThat(callback.mLowMemoryCalled).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDispatchTrimMemory() {
|
||||||
|
final TestComponentCallbacks2 callback = new TestComponentCallbacks2();
|
||||||
|
mController.registerCallbacks(callback);
|
||||||
|
|
||||||
|
mController.dispatchTrimMemory(TRIM_MEMORY_BACKGROUND);
|
||||||
|
|
||||||
|
assertThat(callback.mLevel).isEqualTo(TRIM_MEMORY_BACKGROUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FakeComponentCallbacks implements ComponentCallbacks {
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(@NonNull Configuration newConfig) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLowMemory() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestComponentCallbacks2 implements ComponentCallbacks2 {
|
||||||
|
private Configuration mConfiguration;
|
||||||
|
private boolean mLowMemoryCalled;
|
||||||
|
private int mLevel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||||
|
mConfiguration = newConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLowMemory() {
|
||||||
|
mLowMemoryCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrimMemory(int level) {
|
||||||
|
mLevel = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user