Loading core/java/android/app/ActivityManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -5167,11 +5167,21 @@ public class ActivityManager { * @hide */ public static void broadcastStickyIntent(Intent intent, int appOp, Bundle options, int userId) { broadcastStickyIntent(intent, null, appOp, options, userId); } /** * Convenience for sending a sticky broadcast. For internal use only. * * @hide */ public static void broadcastStickyIntent(Intent intent, String[] excludedPackages, int appOp, Bundle options, int userId) { try { getService().broadcastIntentWithFeature( null, null, intent, null, null, Activity.RESULT_OK, null, null, null /*requiredPermissions*/, null /*excludedPermissions*/, null /*excludedPackages*/, appOp, options, false, true, userId); excludedPackages, appOp, options, false, true, userId); } catch (RemoteException ex) { } } Loading core/java/android/app/ActivityThread.java +23 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,7 @@ import java.util.Objects; import java.util.TimeZone; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** * This manages the execution of the main thread in an Loading Loading @@ -370,6 +371,11 @@ public final class ActivityThread extends ClientTransactionHandler @GuardedBy("mAppThread") private int mLastProcessState = PROCESS_STATE_UNKNOWN; ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>(); @NonNull private final ConfigurationChangedListenerController mConfigurationChangedListenerController = new ConfigurationChangedListenerController(); private int mLastSessionId; // Holds the value of the last reported device ID value from the server for the top activity. int mLastReportedDeviceId; Loading Loading @@ -3540,6 +3546,21 @@ public final class ActivityThread extends ClientTransactionHandler return mConfigurationController.getConfiguration(); } /** * @hide */ public void addConfigurationChangedListener(Executor executor, Consumer<IBinder> consumer) { mConfigurationChangedListenerController.addListener(executor, consumer); } /** * @hide */ public void removeConfigurationChangedListener(Consumer<IBinder> consumer) { mConfigurationChangedListenerController.removeListener(consumer); } @Override public void updatePendingConfiguration(Configuration config) { final Configuration updatedConfig = Loading Loading @@ -6098,6 +6119,8 @@ public final class ActivityThread extends ClientTransactionHandler " did not call through to super.onConfigurationChanged()"); } } mConfigurationChangedListenerController .dispatchOnConfigurationChanged(activity.getActivityToken()); return configToReport; } Loading core/java/android/app/ConfigurationChangedListenerController.java 0 → 100644 +116 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.app; import android.annotation.NonNull; import android.os.IBinder; import com.android.internal.annotations.GuardedBy; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Manages listeners for unfiltered configuration changes. * @hide */ class ConfigurationChangedListenerController { private final Object mLock = new Object(); @GuardedBy("mLock") private final List<ListenerContainer> mListenerContainers = new ArrayList<>(); /** * Adds a listener to receive updates when they are dispatched. This only dispatches updates and * does not relay the last emitted value. If called with the same listener then this method does * not have any effect. * @param executor an executor that is used to dispatch the updates. * @param consumer a listener interested in receiving updates. */ void addListener(@NonNull Executor executor, @NonNull Consumer<IBinder> consumer) { synchronized (mLock) { if (indexOf(consumer) > -1) { return; } mListenerContainers.add(new ListenerContainer(executor, consumer)); } } /** * Removes the listener that was previously registered. If the listener was not registered this * method does not have any effect. */ void removeListener(@NonNull Consumer<IBinder> consumer) { synchronized (mLock) { final int index = indexOf(consumer); if (index > -1) { mListenerContainers.remove(index); } } } /** * Dispatches the update to all registered listeners * @param activityToken a token for the {@link Activity} that received a configuration update. */ void dispatchOnConfigurationChanged(@NonNull IBinder activityToken) { final List<ListenerContainer> consumers; synchronized (mLock) { consumers = new ArrayList<>(mListenerContainers); } for (int i = 0; i < consumers.size(); i++) { consumers.get(i).accept(activityToken); } } @GuardedBy("mLock") private int indexOf(Consumer<IBinder> consumer) { for (int i = 0; i < mListenerContainers.size(); i++) { if (mListenerContainers.get(i).isMatch(consumer)) { return i; } } return -1; } private static final class ListenerContainer { @NonNull private final Executor mExecutor; @NonNull private final Consumer<IBinder> mConsumer; ListenerContainer(@NonNull Executor executor, @NonNull Consumer<IBinder> consumer) { mExecutor = executor; mConsumer = consumer; } public boolean isMatch(@NonNull Consumer<IBinder> consumer) { return mConsumer.equals(consumer); } public void accept(@NonNull IBinder activityToken) { mExecutor.execute(() -> mConsumer.accept(activityToken)); } } } core/java/android/printservice/PrintService.java +1 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ public abstract class PrintService extends Service { * <pre> <print-service * android:vendor="SomeVendor" * android:settingsActivity="foo.bar.MySettingsActivity" * andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity." * android:addPrintersActivity="foo.bar.MyAddPrintersActivity." * . . . * /></pre> * <p> Loading core/java/android/view/inputmethod/RemoteInputConnectionImpl.java +3 −1 Original line number Diff line number Diff line Loading @@ -451,7 +451,9 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { if (mBeamer == null) { return; } dispatch(() -> { mBeamer.forget(token); }); } @Override Loading Loading
core/java/android/app/ActivityManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -5167,11 +5167,21 @@ public class ActivityManager { * @hide */ public static void broadcastStickyIntent(Intent intent, int appOp, Bundle options, int userId) { broadcastStickyIntent(intent, null, appOp, options, userId); } /** * Convenience for sending a sticky broadcast. For internal use only. * * @hide */ public static void broadcastStickyIntent(Intent intent, String[] excludedPackages, int appOp, Bundle options, int userId) { try { getService().broadcastIntentWithFeature( null, null, intent, null, null, Activity.RESULT_OK, null, null, null /*requiredPermissions*/, null /*excludedPermissions*/, null /*excludedPackages*/, appOp, options, false, true, userId); excludedPackages, appOp, options, false, true, userId); } catch (RemoteException ex) { } } Loading
core/java/android/app/ActivityThread.java +23 −0 Original line number Diff line number Diff line Loading @@ -255,6 +255,7 @@ import java.util.Objects; import java.util.TimeZone; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; /** * This manages the execution of the main thread in an Loading Loading @@ -370,6 +371,11 @@ public final class ActivityThread extends ClientTransactionHandler @GuardedBy("mAppThread") private int mLastProcessState = PROCESS_STATE_UNKNOWN; ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>(); @NonNull private final ConfigurationChangedListenerController mConfigurationChangedListenerController = new ConfigurationChangedListenerController(); private int mLastSessionId; // Holds the value of the last reported device ID value from the server for the top activity. int mLastReportedDeviceId; Loading Loading @@ -3540,6 +3546,21 @@ public final class ActivityThread extends ClientTransactionHandler return mConfigurationController.getConfiguration(); } /** * @hide */ public void addConfigurationChangedListener(Executor executor, Consumer<IBinder> consumer) { mConfigurationChangedListenerController.addListener(executor, consumer); } /** * @hide */ public void removeConfigurationChangedListener(Consumer<IBinder> consumer) { mConfigurationChangedListenerController.removeListener(consumer); } @Override public void updatePendingConfiguration(Configuration config) { final Configuration updatedConfig = Loading Loading @@ -6098,6 +6119,8 @@ public final class ActivityThread extends ClientTransactionHandler " did not call through to super.onConfigurationChanged()"); } } mConfigurationChangedListenerController .dispatchOnConfigurationChanged(activity.getActivityToken()); return configToReport; } Loading
core/java/android/app/ConfigurationChangedListenerController.java 0 → 100644 +116 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.app; import android.annotation.NonNull; import android.os.IBinder; import com.android.internal.annotations.GuardedBy; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * Manages listeners for unfiltered configuration changes. * @hide */ class ConfigurationChangedListenerController { private final Object mLock = new Object(); @GuardedBy("mLock") private final List<ListenerContainer> mListenerContainers = new ArrayList<>(); /** * Adds a listener to receive updates when they are dispatched. This only dispatches updates and * does not relay the last emitted value. If called with the same listener then this method does * not have any effect. * @param executor an executor that is used to dispatch the updates. * @param consumer a listener interested in receiving updates. */ void addListener(@NonNull Executor executor, @NonNull Consumer<IBinder> consumer) { synchronized (mLock) { if (indexOf(consumer) > -1) { return; } mListenerContainers.add(new ListenerContainer(executor, consumer)); } } /** * Removes the listener that was previously registered. If the listener was not registered this * method does not have any effect. */ void removeListener(@NonNull Consumer<IBinder> consumer) { synchronized (mLock) { final int index = indexOf(consumer); if (index > -1) { mListenerContainers.remove(index); } } } /** * Dispatches the update to all registered listeners * @param activityToken a token for the {@link Activity} that received a configuration update. */ void dispatchOnConfigurationChanged(@NonNull IBinder activityToken) { final List<ListenerContainer> consumers; synchronized (mLock) { consumers = new ArrayList<>(mListenerContainers); } for (int i = 0; i < consumers.size(); i++) { consumers.get(i).accept(activityToken); } } @GuardedBy("mLock") private int indexOf(Consumer<IBinder> consumer) { for (int i = 0; i < mListenerContainers.size(); i++) { if (mListenerContainers.get(i).isMatch(consumer)) { return i; } } return -1; } private static final class ListenerContainer { @NonNull private final Executor mExecutor; @NonNull private final Consumer<IBinder> mConsumer; ListenerContainer(@NonNull Executor executor, @NonNull Consumer<IBinder> consumer) { mExecutor = executor; mConsumer = consumer; } public boolean isMatch(@NonNull Consumer<IBinder> consumer) { return mConsumer.equals(consumer); } public void accept(@NonNull IBinder activityToken) { mExecutor.execute(() -> mConsumer.accept(activityToken)); } } }
core/java/android/printservice/PrintService.java +1 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ public abstract class PrintService extends Service { * <pre> <print-service * android:vendor="SomeVendor" * android:settingsActivity="foo.bar.MySettingsActivity" * andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity." * android:addPrintersActivity="foo.bar.MyAddPrintersActivity." * . . . * /></pre> * <p> Loading
core/java/android/view/inputmethod/RemoteInputConnectionImpl.java +3 −1 Original line number Diff line number Diff line Loading @@ -451,7 +451,9 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { if (mBeamer == null) { return; } dispatch(() -> { mBeamer.forget(token); }); } @Override Loading