summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/Android.bp9
-rw-r--r--core/java/android/app/IGameManagerService.aidl3
-rw-r--r--core/java/android/app/IGameStateListener.aidl (renamed from core/java/android/flags/SyncableFlag.aidl)15
-rw-r--r--core/java/android/content/Context.java7
-rw-r--r--core/java/android/flags/BooleanFlag.java52
-rw-r--r--core/java/android/flags/BooleanFlagBase.java82
-rw-r--r--core/java/android/flags/DynamicBooleanFlag.java50
-rw-r--r--core/java/android/flags/DynamicFlag.java31
-rw-r--r--core/java/android/flags/FeatureFlags.java379
-rw-r--r--core/java/android/flags/FeatureFlagsFake.java115
-rw-r--r--core/java/android/flags/Flag.java82
-rw-r--r--core/java/android/flags/FusedOffFlag.java49
-rw-r--r--core/java/android/flags/FusedOnFlag.java49
-rw-r--r--core/java/android/flags/IFeatureFlags.aidl89
-rw-r--r--core/java/android/flags/IFeatureFlagsCallback.aidl31
-rw-r--r--core/java/android/flags/OWNERS7
-rw-r--r--core/java/android/flags/SyncableFlag.java112
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java2
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java43
-rw-r--r--core/java/android/os/GraphicsEnvironment.java68
-rw-r--r--core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java6
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java25
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java71
-rw-r--r--core/java/android/view/inputmethod/InputMethodSession.java9
-rw-r--r--core/java/com/android/internal/flags/CoreFlags.java93
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java13
-rw-r--r--core/jni/android_os_GraphicsEnvironment.cpp6
-rw-r--r--core/res/AndroidManifest.xml18
-rw-r--r--core/tests/coretests/src/android/flags/FeatureFlagsTest.java155
-rw-r--r--core/tests/coretests/src/android/flags/IFeatureFlagsFake.java113
-rw-r--r--packages/SystemUI/res/layout/status_bar_wifi_group.xml28
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java249
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java136
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java28
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java5
-rw-r--r--services/Android.bp1
-rw-r--r--services/core/java/com/android/server/app/GameManagerService.java51
-rw-r--r--services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java4
-rw-r--r--services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java5
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java5
-rw-r--r--services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java46
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java36
-rw-r--r--services/flags/Android.bp18
-rw-r--r--services/flags/OWNERS6
-rw-r--r--services/flags/java/com/android/server/flags/DynamicFlagBinderDelegate.java280
-rw-r--r--services/flags/java/com/android/server/flags/FeatureFlagsBinder.java168
-rw-r--r--services/flags/java/com/android/server/flags/FeatureFlagsService.java113
-rw-r--r--services/flags/java/com/android/server/flags/FlagCache.java103
-rw-r--r--services/flags/java/com/android/server/flags/FlagOverrideStore.java122
-rw-r--r--services/flags/java/com/android/server/flags/FlagsShellCommand.java214
-rw-r--r--services/flags/java/com/android/server/flags/GlobalSettingsProxy.java68
-rw-r--r--services/flags/java/com/android/server/flags/SettingsProxy.java381
-rw-r--r--services/java/com/android/server/SystemServer.java18
-rw-r--r--services/midi/java/com/android/server/midi/MidiService.java186
-rw-r--r--services/tests/InputMethodSystemServerTests/AndroidManifest.xml1
-rw-r--r--services/tests/InputMethodSystemServerTests/TEST_MAPPING11
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml2
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java484
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java7
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java30
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java6
-rw-r--r--services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp2
-rw-r--r--services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java66
-rw-r--r--services/tests/servicestests/Android.bp1
-rw-r--r--services/tests/servicestests/src/com/android/server/flags/FeatureFlagsServiceTest.java293
-rw-r--r--services/tests/servicestests/src/com/android/server/flags/FlagCacheTest.java86
-rw-r--r--services/tests/servicestests/src/com/android/server/flags/FlagOverrideStoreTest.java111
-rw-r--r--services/tests/servicestests/src/com/android/server/flags/OWNERS1
84 files changed, 547 insertions, 4928 deletions
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 236d0b5814d7..f8f4cc3523f2 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -34,15 +34,6 @@ filegroup {
}
filegroup {
- name: "feature_flags_aidl",
- srcs: [
- "android/flags/IFeatureFlags.aidl",
- "android/flags/IFeatureFlagsCallback.aidl",
- "android/flags/SyncableFlag.aidl",
- ],
-}
-
-filegroup {
name: "ITracingServiceProxy.aidl",
srcs: ["android/tracing/ITracingServiceProxy.aidl"],
}
diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl
index 3d6ab6fd9478..9a818e49ae4a 100644
--- a/core/java/android/app/IGameManagerService.aidl
+++ b/core/java/android/app/IGameManagerService.aidl
@@ -20,6 +20,7 @@ import android.app.GameModeConfiguration;
import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameModeListener;
+import android.app.IGameStateListener;
/**
* @hide
@@ -49,4 +50,6 @@ interface IGameManagerService {
void addGameModeListener(IGameModeListener gameModeListener);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)")
void removeGameModeListener(IGameModeListener gameModeListener);
+ void addGameStateListener(IGameStateListener gameStateListener);
+ void removeGameStateListener(IGameStateListener gameStateListener);
}
diff --git a/core/java/android/flags/SyncableFlag.aidl b/core/java/android/app/IGameStateListener.aidl
index 1526ec148967..34cff489d077 100644
--- a/core/java/android/flags/SyncableFlag.aidl
+++ b/core/java/android/app/IGameStateListener.aidl
@@ -14,9 +14,14 @@
* limitations under the License.
*/
-package android.flags;
+package android.app;
-/**
- * A parcelable data class for serializing {@link Flag} across a Binder.
- */
-parcelable SyncableFlag; \ No newline at end of file
+import android.app.GameState;
+
+/** @hide */
+interface IGameStateListener {
+ /**
+ * Called when the state of the game has changed.
+ */
+ oneway void onGameStateChanged(String packageName, in GameState state, int userId);
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2a6d84b1acc6..6d82922484bc 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5298,13 +5298,6 @@ public abstract class Context {
public static final String APP_PREDICTION_SERVICE = "app_prediction";
/**
- * Used for reading system-wide, overridable flags.
- *
- * @hide
- */
- public static final String FEATURE_FLAGS_SERVICE = "feature_flags";
-
- /**
* Official published name of the search ui service.
*
* <p><b>NOTE: </b> this service is optional; callers of
diff --git a/core/java/android/flags/BooleanFlag.java b/core/java/android/flags/BooleanFlag.java
deleted file mode 100644
index d4a35b25f623..000000000000
--- a/core/java/android/flags/BooleanFlag.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-
-/**
- * A flag representing a true or false value.
- *
- * The value will always be the same during the lifetime of the process it is read in.
- *
- * @hide
- */
-public class BooleanFlag extends BooleanFlagBase {
- private final boolean mDefault;
-
- /**
- * @param namespace A namespace for this flag. See {@link android.provider.DeviceConfig}.
- * @param name A name for this flag.
- * @param defaultValue The value of this flag if no other override is present.
- */
- BooleanFlag(String namespace, String name, boolean defaultValue) {
- super(namespace, name);
- mDefault = defaultValue;
- }
-
- @Override
- @NonNull
- public Boolean getDefault() {
- return mDefault;
- }
-
- @Override
- public BooleanFlag defineMetaData(String label, String description, String categoryName) {
- super.defineMetaData(label, description, categoryName);
- return this;
- }
-}
diff --git a/core/java/android/flags/BooleanFlagBase.java b/core/java/android/flags/BooleanFlagBase.java
deleted file mode 100644
index 985dbe3f2f01..000000000000
--- a/core/java/android/flags/BooleanFlagBase.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-
-abstract class BooleanFlagBase implements Flag<Boolean> {
-
- private final String mNamespace;
- private final String mName;
- private String mLabel;
- private String mDescription;
- private String mCategoryName;
-
- /**
- * @param namespace A namespace for this flag. See {@link android.provider.DeviceConfig}.
- * @param name A name for this flag.
- */
- BooleanFlagBase(String namespace, String name) {
- mNamespace = namespace;
- mName = name;
- mLabel = name;
- }
-
- public abstract Boolean getDefault();
-
- @Override
- @NonNull
- public String getNamespace() {
- return mNamespace;
- }
-
- @Override
- @NonNull
- public String getName() {
- return mName;
- }
-
- @Override
- public BooleanFlagBase defineMetaData(String label, String description, String categoryName) {
- mLabel = label;
- mDescription = description;
- mCategoryName = categoryName;
- return this;
- }
-
- @Override
- @NonNull
- public String getLabel() {
- return mLabel;
- }
-
- @Override
- public String getDescription() {
- return mDescription;
- }
-
- @Override
- public String getCategoryName() {
- return mCategoryName;
- }
-
- @Override
- @NonNull
- public String toString() {
- return getNamespace() + "." + getName() + "[" + getDefault() + "]";
- }
-}
diff --git a/core/java/android/flags/DynamicBooleanFlag.java b/core/java/android/flags/DynamicBooleanFlag.java
deleted file mode 100644
index 271a8c5f4d15..000000000000
--- a/core/java/android/flags/DynamicBooleanFlag.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.flags;
-
-/**
- * A flag representing a true or false value.
- *
- * The value may be different from one read to the next.
- *
- * @hide
- */
-public class DynamicBooleanFlag extends BooleanFlagBase implements DynamicFlag<Boolean> {
-
- private final boolean mDefault;
-
- /**
- * @param namespace A namespace for this flag. See {@link android.provider.DeviceConfig}.
- * @param name A name for this flag.
- * @param defaultValue The value of this flag if no other override is present.
- */
- DynamicBooleanFlag(String namespace, String name, boolean defaultValue) {
- super(namespace, name);
- mDefault = defaultValue;
- }
-
- @Override
- public Boolean getDefault() {
- return mDefault;
- }
-
- @Override
- public DynamicBooleanFlag defineMetaData(String label, String description, String categoryName) {
- super.defineMetaData(label, description, categoryName);
- return this;
- }
-}
diff --git a/core/java/android/flags/DynamicFlag.java b/core/java/android/flags/DynamicFlag.java
deleted file mode 100644
index 68819c58c064..000000000000
--- a/core/java/android/flags/DynamicFlag.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.flags;
-
-/**
- * A flag for which the value may be different from one read to the next.
- *
- * @param <T> The type of value that this flag stores. E.g. Boolean or String.
- *
- * @hide
- */
-public interface DynamicFlag<T> extends Flag<T> {
- @Override
- default boolean isDynamic() {
- return true;
- }
-}
diff --git a/core/java/android/flags/FeatureFlags.java b/core/java/android/flags/FeatureFlags.java
deleted file mode 100644
index 8d3112c35d51..000000000000
--- a/core/java/android/flags/FeatureFlags.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A class for querying constants from the system - primarily booleans.
- *
- * Clients using this class can define their flags and their default values in one place,
- * can override those values on running devices for debugging and testing purposes, and can control
- * what flags are available to be used on release builds.
- *
- * TODO(b/279054964): A lot. This is skeleton code right now.
- * @hide
- */
-public class FeatureFlags {
- private static final String TAG = "FeatureFlags";
- private static FeatureFlags sInstance;
- private static final Object sInstanceLock = new Object();
-
- private final Set<Flag<?>> mKnownFlags = new ArraySet<>();
- private final Set<Flag<?>> mDirtyFlags = new ArraySet<>();
-
- private IFeatureFlags mIFeatureFlags;
- private final Map<String, Map<String, Boolean>> mBooleanOverrides = new HashMap<>();
- private final Set<ChangeListener> mListeners = new HashSet<>();
-
- /**
- * Obtain a per-process instance of FeatureFlags.
- * @return A singleton instance of {@link FeatureFlags}.
- */
- @NonNull
- public static FeatureFlags getInstance() {
- synchronized (sInstanceLock) {
- if (sInstance == null) {
- sInstance = new FeatureFlags();
- }
- }
-
- return sInstance;
- }
-
- /** See {@link FeatureFlagsFake}. */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public static void setInstance(FeatureFlags instance) {
- synchronized (sInstanceLock) {
- sInstance = instance;
- }
- }
-
- private final IFeatureFlagsCallback mIFeatureFlagsCallback = new IFeatureFlagsCallback.Stub() {
- @Override
- public void onFlagChange(SyncableFlag flag) {
- for (Flag<?> f : mKnownFlags) {
- if (flagEqualsSyncableFlag(f, flag)) {
- if (f instanceof DynamicFlag<?>) {
- if (f instanceof DynamicBooleanFlag) {
- String value = flag.getValue();
- if (value == null) { // Null means any existing overrides were erased.
- value = ((DynamicBooleanFlag) f).getDefault().toString();
- }
- addBooleanOverride(flag.getNamespace(), flag.getName(), value);
- }
- FeatureFlags.this.onFlagChange((DynamicFlag<?>) f);
- }
- break;
- }
- }
- }
- };
-
- private FeatureFlags() {
- this(null);
- }
-
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public FeatureFlags(IFeatureFlags iFeatureFlags) {
- mIFeatureFlags = iFeatureFlags;
-
- if (mIFeatureFlags != null) {
- try {
- mIFeatureFlags.registerCallback(mIFeatureFlagsCallback);
- } catch (RemoteException e) {
- // Shouldn't happen with things passed into tests.
- Log.e(TAG, "Could not register callbacks!", e);
- }
- }
- }
-
- /**
- * Construct a new {@link BooleanFlag}.
- *
- * Use this instead of constructing a {@link BooleanFlag} directly, as it registers the flag
- * with the internals of the flagging system.
- */
- @NonNull
- public static BooleanFlag booleanFlag(
- @NonNull String namespace, @NonNull String name, boolean def) {
- return getInstance().addFlag(new BooleanFlag(namespace, name, def));
- }
-
- /**
- * Construct a new {@link FusedOffFlag}.
- *
- * Use this instead of constructing a {@link FusedOffFlag} directly, as it registers the
- * flag with the internals of the flagging system.
- */
- @NonNull
- public static FusedOffFlag fusedOffFlag(@NonNull String namespace, @NonNull String name) {
- return getInstance().addFlag(new FusedOffFlag(namespace, name));
- }
-
- /**
- * Construct a new {@link FusedOnFlag}.
- *
- * Use this instead of constructing a {@link FusedOnFlag} directly, as it registers the flag
- * with the internals of the flagging system.
- */
- @NonNull
- public static FusedOnFlag fusedOnFlag(@NonNull String namespace, @NonNull String name) {
- return getInstance().addFlag(new FusedOnFlag(namespace, name));
- }
-
- /**
- * Construct a new {@link DynamicBooleanFlag}.
- *
- * Use this instead of constructing a {@link DynamicBooleanFlag} directly, as it registers
- * the flag with the internals of the flagging system.
- */
- @NonNull
- public static DynamicBooleanFlag dynamicBooleanFlag(
- @NonNull String namespace, @NonNull String name, boolean def) {
- return getInstance().addFlag(new DynamicBooleanFlag(namespace, name, def));
- }
-
- /**
- * Add a listener to be alerted when a {@link DynamicFlag} changes.
- *
- * See also {@link #removeChangeListener(ChangeListener)}.
- *
- * @param listener The listener to add.
- */
- public void addChangeListener(@NonNull ChangeListener listener) {
- mListeners.add(listener);
- }
-
- /**
- * Remove a listener that was added earlier.
- *
- * See also {@link #addChangeListener(ChangeListener)}.
- *
- * @param listener The listener to remove.
- */
- public void removeChangeListener(@NonNull ChangeListener listener) {
- mListeners.remove(listener);
- }
-
- protected void onFlagChange(@NonNull DynamicFlag<?> flag) {
- for (ChangeListener l : mListeners) {
- l.onFlagChanged(flag);
- }
- }
-
- /**
- * Returns whether the supplied flag is true or not.
- *
- * {@link BooleanFlag} should only be used in debug builds. They do not get optimized out.
- *
- * The first time a flag is read, its value is cached for the lifetime of the process.
- */
- public boolean isEnabled(@NonNull BooleanFlag flag) {
- return getBooleanInternal(flag);
- }
-
- /**
- * Returns whether the supplied flag is true or not.
- *
- * Always returns false.
- */
- public boolean isEnabled(@NonNull FusedOffFlag flag) {
- return false;
- }
-
- /**
- * Returns whether the supplied flag is true or not.
- *
- * Always returns true;
- */
- public boolean isEnabled(@NonNull FusedOnFlag flag) {
- return true;
- }
-
- /**
- * Returns whether the supplied flag is true or not.
- *
- * Can return a different value for the flag each time it is called if an override comes in.
- */
- public boolean isCurrentlyEnabled(@NonNull DynamicBooleanFlag flag) {
- return getBooleanInternal(flag);
- }
-
- private boolean getBooleanInternal(Flag<Boolean> flag) {
- sync();
- Map<String, Boolean> ns = mBooleanOverrides.get(flag.getNamespace());
- Boolean value = null;
- if (ns != null) {
- value = ns.get(flag.getName());
- }
- if (value == null) {
- throw new IllegalStateException("Boolean flag being read but was not synced: " + flag);
- }
-
- return value;
- }
-
- private <T extends Flag<?>> T addFlag(T flag) {
- synchronized (FeatureFlags.class) {
- mDirtyFlags.add(flag);
- mKnownFlags.add(flag);
- }
- return flag;
- }
-
- /**
- * Sync any known flags that have not yet been synced.
- *
- * This is called implicitly when any flag is read, and is not generally needed except in
- * exceptional circumstances.
- */
- public void sync() {
- synchronized (FeatureFlags.class) {
- if (mDirtyFlags.isEmpty()) {
- return;
- }
- syncInternal(mDirtyFlags);
- mDirtyFlags.clear();
- }
- }
-
- /**
- * Called when new flags have been declared. Gives the implementation a chance to act on them.
- *
- * Guaranteed to be called from a synchronized, thread-safe context.
- */
- protected void syncInternal(Set<Flag<?>> dirtyFlags) {
- IFeatureFlags iFeatureFlags = bind();
- List<SyncableFlag> syncableFlags = new ArrayList<>();
- for (Flag<?> f : dirtyFlags) {
- syncableFlags.add(flagToSyncableFlag(f));
- }
-
- List<SyncableFlag> serverFlags = List.of(); // Need to initialize the list with something.
- try {
- // New values come back from the service.
- serverFlags = iFeatureFlags.syncFlags(syncableFlags);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
-
- for (Flag<?> f : dirtyFlags) {
- boolean found = false;
- for (SyncableFlag sf : serverFlags) {
- if (flagEqualsSyncableFlag(f, sf)) {
- if (f instanceof BooleanFlag || f instanceof DynamicBooleanFlag) {
- addBooleanOverride(sf.getNamespace(), sf.getName(), sf.getValue());
- }
- found = true;
- break;
- }
- }
- if (!found) {
- if (f instanceof BooleanFlag) {
- addBooleanOverride(
- f.getNamespace(),
- f.getName(),
- ((BooleanFlag) f).getDefault() ? "true" : "false");
- }
- }
- }
- }
-
- private void addBooleanOverride(String namespace, String name, String override) {
- Map<String, Boolean> nsOverrides = mBooleanOverrides.get(namespace);
- if (nsOverrides == null) {
- nsOverrides = new HashMap<>();
- mBooleanOverrides.put(namespace, nsOverrides);
- }
- nsOverrides.put(name, parseBoolean(override));
- }
-
- private SyncableFlag flagToSyncableFlag(Flag<?> f) {
- return new SyncableFlag(
- f.getNamespace(),
- f.getName(),
- f.getDefault().toString(),
- f instanceof DynamicFlag<?>);
- }
-
- private IFeatureFlags bind() {
- if (mIFeatureFlags == null) {
- mIFeatureFlags = IFeatureFlags.Stub.asInterface(
- ServiceManager.getService(Context.FEATURE_FLAGS_SERVICE));
- try {
- mIFeatureFlags.registerCallback(mIFeatureFlagsCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to listen for flag changes!");
- }
- }
-
- return mIFeatureFlags;
- }
-
- static boolean parseBoolean(String value) {
- // Check for a truish string.
- boolean result = value.equalsIgnoreCase("true")
- || value.equals("1")
- || value.equalsIgnoreCase("t")
- || value.equalsIgnoreCase("on");
- if (!result) { // Expect a falsish string, else log an error.
- if (!(value.equalsIgnoreCase("false")
- || value.equals("0")
- || value.equalsIgnoreCase("f")
- || value.equalsIgnoreCase("off"))) {
- Log.e(TAG,
- "Tried parsing " + value + " as boolean but it doesn't look like one. "
- + "Value expected to be one of true|false, 1|0, t|f, on|off.");
- }
- }
- return result;
- }
-
- private static boolean flagEqualsSyncableFlag(Flag<?> f, SyncableFlag sf) {
- return f.getName().equals(sf.getName()) && f.getNamespace().equals(sf.getNamespace());
- }
-
-
- /**
- * A simpler listener that is alerted when a {@link DynamicFlag} changes.
- *
- * See {@link #addChangeListener(ChangeListener)}
- */
- public interface ChangeListener {
- /**
- * Called when a {@link DynamicFlag} changes.
- *
- * @param flag The flag that has changed.
- */
- void onFlagChanged(DynamicFlag<?> flag);
- }
-}
diff --git a/core/java/android/flags/FeatureFlagsFake.java b/core/java/android/flags/FeatureFlagsFake.java
deleted file mode 100644
index daedcdae0b5f..000000000000
--- a/core/java/android/flags/FeatureFlagsFake.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * An implementation of {@link FeatureFlags} for testing.
- *
- * Before you read a flag from using this Fake, you must set that flag using
- * {@link #setFlagValue(BooleanFlagBase, boolean)}. This ensures that your tests are deterministic.
- *
- * If you are relying on {@link FeatureFlags#getInstance()} to access FeatureFlags in your code
- * under test, (instead of dependency injection), you can pass an instance of this fake to
- * {@link FeatureFlags#setInstance(FeatureFlags)}. Be sure to call that method again, passing null,
- * to ensure hermetic testing - you don't want static state persisting between your test methods.
- *
- * @hide
- */
-public class FeatureFlagsFake extends FeatureFlags {
- private final Map<BooleanFlagBase, Boolean> mFlagValues = new HashMap<>();
- private final Set<BooleanFlagBase> mReadFlags = new HashSet<>();
-
- public FeatureFlagsFake(IFeatureFlags iFeatureFlags) {
- super(iFeatureFlags);
- }
-
- @Override
- public boolean isEnabled(@NonNull BooleanFlag flag) {
- return requireFlag(flag);
- }
-
- @Override
- public boolean isEnabled(@NonNull FusedOffFlag flag) {
- return requireFlag(flag);
- }
-
- @Override
- public boolean isEnabled(@NonNull FusedOnFlag flag) {
- return requireFlag(flag);
- }
-
- @Override
- public boolean isCurrentlyEnabled(@NonNull DynamicBooleanFlag flag) {
- return requireFlag(flag);
- }
-
- @Override
- protected void syncInternal(Set<Flag<?>> dirtyFlags) {
- }
-
- /**
- * Explicitly set a flag's value for reading in tests.
- *
- * You _must_ call this for every flag your code-under-test will read. Otherwise, an
- * {@link IllegalStateException} will be thrown.
- *
- * You are able to set values for {@link FusedOffFlag} and {@link FusedOnFlag}, despite those
- * flags having a fixed value at compile time, since unit tests should still test the state of
- * those flags as both true and false. I.e. a flag that is off might be turned on in a future
- * build or vice versa.
- *
- * You can not call this method _after_ a non-dynamic flag has been read. Non-dynamic flags
- * are held stable in the system, so changing a value after reading would not match
- * real-implementation behavior.
- *
- * Calling this method will trigger any {@link android.flags.FeatureFlags.ChangeListener}s that
- * are registered for the supplied flag if the flag is a {@link DynamicFlag}.
- *
- * @param flag The BooleanFlag that you want to set a value for.
- * @param value The value that the flag should return when accessed.
- */
- public void setFlagValue(@NonNull BooleanFlagBase flag, boolean value) {
- if (!(flag instanceof DynamicBooleanFlag) && mReadFlags.contains(flag)) {
- throw new RuntimeException(
- "You can not set the value of a flag after it has been read. Tried to set "
- + flag + " to " + value + " but it already " + mFlagValues.get(flag));
- }
- mFlagValues.put(flag, value);
- if (flag instanceof DynamicBooleanFlag) {
- onFlagChange((DynamicFlag<?>) flag);
- }
- }
-
- private boolean requireFlag(BooleanFlagBase flag) {
- if (!mFlagValues.containsKey(flag)) {
- throw new IllegalStateException(
- "Tried to access " + flag + " in test but no overrided specified. You must "
- + "call #setFlagValue for each flag read in a test.");
- }
- mReadFlags.add(flag);
-
- return mFlagValues.get(flag);
- }
-
-}
diff --git a/core/java/android/flags/Flag.java b/core/java/android/flags/Flag.java
deleted file mode 100644
index b97a4c8a0fe7..000000000000
--- a/core/java/android/flags/Flag.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-
-/**
- * Base class for constants read via {@link android.flags.FeatureFlags}.
- *
- * @param <T> The type of value that this flag stores. E.g. Boolean or String.
- *
- * @hide
- */
-public interface Flag<T> {
- /** The namespace for a flag. Should combine uniquely with its name. */
- @NonNull
- String getNamespace();
-
- /** The name of the flag. Should combine uniquely with its namespace. */
- @NonNull
- String getName();
-
- /** The value of this flag if no override has been set. Null values are not supported. */
- @NonNull
- T getDefault();
-
- /** Returns true if the value of this flag can change at runtime. */
- default boolean isDynamic() {
- return false;
- }
-
- /**
- * Add human-readable details to the flag. Flag client's are not required to set this.
- *
- * See {@link #getLabel()}, {@link #getDescription()}, and {@link #getCategoryName()}.
- *
- * @return Returns `this`, to make a fluent api.
- */
- Flag<T> defineMetaData(String label, String description, String categoryName);
-
- /**
- * A human-readable name for the flag. Defaults to {@link #getName()}
- *
- * See {@link #defineMetaData(String, String, String)}
- */
- @NonNull
- default String getLabel() {
- return getName();
- }
-
- /**
- * A human-readable description for the flag. Defaults to null if unset.
- *
- * See {@link #defineMetaData(String, String, String)}
- */
- default String getDescription() {
- return null;
- }
-
- /**
- * A human-readable category name for the flag. Defaults to null if unset.
- *
- * See {@link #defineMetaData(String, String, String)}
- */
- default String getCategoryName() {
- return null;
- }
-}
diff --git a/core/java/android/flags/FusedOffFlag.java b/core/java/android/flags/FusedOffFlag.java
deleted file mode 100644
index 6844b8faafef..000000000000
--- a/core/java/android/flags/FusedOffFlag.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-import android.provider.DeviceConfig;
-
-/**
- * A flag representing a false value.
- *
- * The flag can never be changed or overridden. It is false at compile time.
- *
- * @hide
- */
-public final class FusedOffFlag extends BooleanFlagBase {
- /**
- * @param namespace A namespace for this flag. See {@link DeviceConfig}.
- * @param name A name for this flag.
- */
- FusedOffFlag(String namespace, String name) {
- super(namespace, name);
- }
-
- @Override
- @NonNull
- public Boolean getDefault() {
- return false;
- }
-
- @Override
- public FusedOffFlag defineMetaData(String label, String description, String categoryName) {
- super.defineMetaData(label, description, categoryName);
- return this;
- }
-}
diff --git a/core/java/android/flags/FusedOnFlag.java b/core/java/android/flags/FusedOnFlag.java
deleted file mode 100644
index e9adba7595c1..000000000000
--- a/core/java/android/flags/FusedOnFlag.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-import android.provider.DeviceConfig;
-
-/**
- * A flag representing a true value.
- *
- * The flag can never be changed or overridden. It is true at compile time.
- *
- * @hide
- */
-public final class FusedOnFlag extends BooleanFlagBase {
- /**
- * @param namespace A namespace for this flag. See {@link DeviceConfig}.
- * @param name A name for this flag.
- */
- FusedOnFlag(String namespace, String name) {
- super(namespace, name);
- }
-
- @Override
- @NonNull
- public Boolean getDefault() {
- return true;
- }
-
- @Override
- public FusedOnFlag defineMetaData(String label, String description, String categoryName) {
- super.defineMetaData(label, description, categoryName);
- return this;
- }
-}
diff --git a/core/java/android/flags/IFeatureFlags.aidl b/core/java/android/flags/IFeatureFlags.aidl
deleted file mode 100644
index 3efcec97fe6d..000000000000
--- a/core/java/android/flags/IFeatureFlags.aidl
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.flags;
-
-import android.flags.IFeatureFlagsCallback;
-import android.flags.SyncableFlag;
-
-/**
- * Binder interface for communicating with {@link com.android.server.flags.FeatureFlagsService}.
- *
- * This interface is used by {@link android.flags.FeatureFlags} and developers should use that to
- * interface with the service. FeatureFlags is the "client" in this documentation.
- *
- * The methods allow client apps to communicate what flags they care about, and receive back
- * current values for those flags. For stable flags, this is the finalized value until the device
- * restarts. For {@link DynamicFlag}s, this is the last known value, though it may change in the
- * future. Clients can listen for changes to flag values so that it can react accordingly.
- * @hide
- */
-interface IFeatureFlags {
- /**
- * Synchronize with the {@link com.android.server.flags.FeatureFlagsService} about flags of
- * interest.
- *
- * The client should pass in a list of flags that it is using as {@link SyncableFlag}s, which
- * includes what it thinks the default values of the flags are.
- *
- * The response will contain a list of matching SyncableFlags, whose values are set to what the
- * value of the flags actually are. The client should update its internal state flag data to
- * match.
- *
- * Generally speaking, if a flag that is passed in is new to the FeatureFlagsService, the
- * service will cache the passed-in value, and return it back out. If, however, a different
- * client has synced that flag with the service previously, FeatureFlagsService will return the
- * existing cached value, which may or may not be what the current client passed in. This allows
- * FeatureFlagsService to keep clients in agreement with one another.
- */
- List<SyncableFlag> syncFlags(in List<SyncableFlag> flagList);
-
- /**
- * Pass in an {@link IFeatureFlagsCallback} that will be called whenever a {@link DymamicFlag}
- * changes.
- */
- void registerCallback(IFeatureFlagsCallback callback);
-
- /**
- * Remove a {@link IFeatureFlagsCallback} that was previously registered with
- * {@link #registerCallback}.
- */
- void unregisterCallback(IFeatureFlagsCallback callback);
-
- /**
- * Query the {@link com.android.server.flags.FeatureFlagsService} for flags, but don't
- * cache them. See {@link #syncFlags}.
- *
- * You almost certainly don't want this method. This is intended for the Flag Flipper
- * application that needs to query the state of system but doesn't want to affect it by
- * doing so. All other clients should use {@link syncFlags}.
- */
- List<SyncableFlag> queryFlags(in List<SyncableFlag> flagList);
-
- /**
- * Change a flags value in the system.
- *
- * This is intended for use by the Flag Flipper application.
- */
- void overrideFlag(in SyncableFlag flag);
-
- /**
- * Restore a flag to its default value.
- *
- * This is intended for use by the Flag Flipper application.
- */
- void resetFlag(in SyncableFlag flag);
-} \ No newline at end of file
diff --git a/core/java/android/flags/IFeatureFlagsCallback.aidl b/core/java/android/flags/IFeatureFlagsCallback.aidl
deleted file mode 100644
index f708667ea4c4..000000000000
--- a/core/java/android/flags/IFeatureFlagsCallback.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.flags;
-
-import android.flags.SyncableFlag;
-
-/**
- * Callback for {@link IFeatureFlags#registerCallback} to get alerts when a {@link DynamicFlag}
- * changes.
- *
- * DynamicFlags can change at run time. Stable flags will never result in a call to this method.
- *
- * @hide
- */
-oneway interface IFeatureFlagsCallback {
- void onFlagChange(in SyncableFlag flag);
-} \ No newline at end of file
diff --git a/core/java/android/flags/OWNERS b/core/java/android/flags/OWNERS
deleted file mode 100644
index fa125c4a159c..000000000000
--- a/core/java/android/flags/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-# Bug component: 1306523
-
-mankoff@google.com
-pixel@google.com
-
-dsandler@android.com
-
diff --git a/core/java/android/flags/SyncableFlag.java b/core/java/android/flags/SyncableFlag.java
deleted file mode 100644
index 449bcc3c49f5..000000000000
--- a/core/java/android/flags/SyncableFlag.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.flags;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * @hide
- */
-public final class SyncableFlag implements Parcelable {
- private final String mNamespace;
- private final String mName;
- private final String mValue;
- private final boolean mDynamic;
- private final boolean mOverridden;
-
- public SyncableFlag(
- @NonNull String namespace,
- @NonNull String name,
- @NonNull String value,
- boolean dynamic) {
- this(namespace, name, value, dynamic, false);
- }
-
- public SyncableFlag(
- @NonNull String namespace,
- @NonNull String name,
- @NonNull String value,
- boolean dynamic,
- boolean overridden
- ) {
- mNamespace = namespace;
- mName = name;
- mValue = value;
- mDynamic = dynamic;
- mOverridden = overridden;
- }
-
- @NonNull
- public String getNamespace() {
- return mNamespace;
- }
-
- @NonNull
- public String getName() {
- return mName;
- }
-
- @NonNull
- public String getValue() {
- return mValue;
- }
-
- public boolean isDynamic() {
- return mDynamic;
- }
-
- public boolean isOverridden() {
- return mOverridden;
- }
-
- @NonNull
- public static final Parcelable.Creator<SyncableFlag> CREATOR = new Parcelable.Creator<>() {
- public SyncableFlag createFromParcel(Parcel in) {
- return new SyncableFlag(
- in.readString(),
- in.readString(),
- in.readString(),
- in.readBoolean(),
- in.readBoolean());
- }
-
- public SyncableFlag[] newArray(int size) {
- return new SyncableFlag[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mNamespace);
- dest.writeString(mName);
- dest.writeString(mValue);
- dest.writeBoolean(mDynamic);
- dest.writeBoolean(mOverridden);
- }
-
- @Override
- public String toString() {
- return getNamespace() + "." + getName() + "[" + getValue() + "]";
- }
-}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index b99996ff83c8..70b72c809524 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -433,7 +433,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
- @InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
+ int flags, ResultReceiver resultReceiver) {
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT,
flags, showInputToken, resultReceiver, statsToken));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index e1d2c32fe101..a9c4818393a8 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -607,7 +607,6 @@ public class InputMethodService extends AbstractInputMethodService {
InputConnection mStartedInputConnection;
EditorInfo mInputEditorInfo;
- @InputMethod.ShowFlags
int mShowInputFlags;
boolean mShowInputRequested;
boolean mLastShowInputRequested;
@@ -932,9 +931,8 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@MainThread
@Override
- public void showSoftInputWithToken(@InputMethod.ShowFlags int flags,
- ResultReceiver resultReceiver, IBinder showInputToken,
- @Nullable ImeTracker.Token statsToken) {
+ public void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
+ IBinder showInputToken, @Nullable ImeTracker.Token statsToken) {
mSystemCallingShowSoftInput = true;
mCurShowInputToken = showInputToken;
mCurStatsToken = statsToken;
@@ -952,7 +950,7 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@MainThread
@Override
- public void showSoftInput(@InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
+ public void showSoftInput(int flags, ResultReceiver resultReceiver) {
ImeTracker.forLogging().onProgress(
mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
if (DEBUG) Log.v(TAG, "showSoftInput()");
@@ -1323,8 +1321,7 @@ public class InputMethodService extends AbstractInputMethodService {
* InputMethodService#requestShowSelf} or {@link InputMethodService#requestHideSelf}
*/
@Deprecated
- public void toggleSoftInput(@InputMethodManager.ShowFlags int showFlags,
- @InputMethodManager.HideFlags int hideFlags) {
+ public void toggleSoftInput(int showFlags, int hideFlags) {
InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
}
@@ -2796,16 +2793,18 @@ public class InputMethodService extends AbstractInputMethodService {
* {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
* and the current configuration to decide whether the input view should
* be shown at this point.
- *
+ *
+ * @param flags Provides additional information about the show request,
+ * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
* @param configChange This is true if we are re-showing due to a
* configuration change.
* @return Returns true to indicate that the window should be shown.
*/
- public boolean onShowInputRequested(@InputMethod.ShowFlags int flags, boolean configChange) {
+ public boolean onShowInputRequested(int flags, boolean configChange) {
if (!onEvaluateInputViewShown()) {
return false;
}
- if ((flags & InputMethod.SHOW_EXPLICIT) == 0) {
+ if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
if (!configChange && onEvaluateFullscreenMode() && !isInputViewShown()) {
// Don't show if this is not explicitly requested by the user and
// the input method is fullscreen unless it is already shown. That
@@ -2831,14 +2830,14 @@ public class InputMethodService extends AbstractInputMethodService {
* exposed to IME authors as an overridable public method without {@code @CallSuper}, we have
* to have this method to ensure that those internal states are always updated no matter how
* {@link #onShowInputRequested(int, boolean)} is overridden by the IME author.
- *
+ * @param flags Provides additional information about the show request,
+ * as per {@link InputMethod#showSoftInput InputMethod.showSoftInput()}.
* @param configChange This is true if we are re-showing due to a
* configuration change.
* @return Returns true to indicate that the window should be shown.
* @see #onShowInputRequested(int, boolean)
*/
- private boolean dispatchOnShowInputRequested(@InputMethod.ShowFlags int flags,
- boolean configChange) {
+ private boolean dispatchOnShowInputRequested(int flags, boolean configChange) {
final boolean result = onShowInputRequested(flags, configChange);
mInlineSuggestionSessionController.notifyOnShowInputRequested(result);
if (result) {
@@ -3271,13 +3270,16 @@ public class InputMethodService extends AbstractInputMethodService {
*
* The input method will continue running, but the user can no longer use it to generate input
* by touching the screen.
+ *
+ * @see InputMethodManager#HIDE_IMPLICIT_ONLY
+ * @see InputMethodManager#HIDE_NOT_ALWAYS
+ * @param flags Provides additional operating flags.
*/
- public void requestHideSelf(@InputMethodManager.HideFlags int flags) {
+ public void requestHideSelf(int flags) {
requestHideSelf(flags, SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME);
}
- private void requestHideSelf(@InputMethodManager.HideFlags int flags,
- @SoftInputShowHideReason int reason) {
+ private void requestHideSelf(int flags, @SoftInputShowHideReason int reason) {
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestHideSelf", mDumper,
null /* icProto */);
mPrivOps.hideMySoftInput(flags, reason);
@@ -3286,8 +3288,12 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* Show the input method's soft input area, so the user sees the input method window and can
* interact with it.
+ *
+ * @see InputMethodManager#SHOW_IMPLICIT
+ * @see InputMethodManager#SHOW_FORCED
+ * @param flags Provides additional operating flags.
*/
- public final void requestShowSelf(@InputMethodManager.ShowFlags int flags) {
+ public final void requestShowSelf(int flags) {
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestShowSelf", mDumper,
null /* icProto */);
mPrivOps.showMySoftInput(flags);
@@ -3447,8 +3453,7 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* Handle a request by the system to toggle the soft input area.
*/
- private void onToggleSoftInput(@InputMethodManager.ShowFlags int showFlags,
- @InputMethodManager.HideFlags int hideFlags) {
+ private void onToggleSoftInput(int showFlags, int hideFlags) {
if (DEBUG) Log.v(TAG, "toggleSoftInput()");
if (isInputViewShown()) {
requestHideSelf(
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 7664bada2c28..e6bdfe1b95c4 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -112,17 +112,9 @@ public class GraphicsEnvironment {
private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0;
// Values for ANGLE_GL_DRIVER_SELECTION_VALUES
- private enum AngleDriverChoice {
- DEFAULT("default"),
- ANGLE("angle"),
- NATIVE("native");
-
- public final String choice;
-
- AngleDriverChoice(String choice) {
- this.choice = choice;
- }
- }
+ private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default";
+ private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle";
+ private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native";
private static final String PROPERTY_RO_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
@@ -203,16 +195,15 @@ public class GraphicsEnvironment {
}
/**
- * Query to determine the ANGLE driver choice.
+ * Query to determine if ANGLE should be used
*/
- private AngleDriverChoice queryAngleChoice(Context context, Bundle coreSettings,
- String packageName) {
+ private boolean shouldUseAngle(Context context, Bundle coreSettings, String packageName) {
if (TextUtils.isEmpty(packageName)) {
Log.v(TAG, "No package name specified; use the system driver");
- return AngleDriverChoice.DEFAULT;
+ return false;
}
- return queryAngleChoiceInternal(context, coreSettings, packageName);
+ return shouldUseAngleInternal(context, coreSettings, packageName);
}
private int getVulkanVersion(PackageManager pm) {
@@ -433,11 +424,10 @@ public class GraphicsEnvironment {
* forces a choice;
* 3) Use ANGLE if isAngleEnabledByGameMode() returns true;
*/
- private AngleDriverChoice queryAngleChoiceInternal(Context context, Bundle bundle,
- String packageName) {
+ private boolean shouldUseAngleInternal(Context context, Bundle bundle, String packageName) {
// Make sure we have a good package name
if (TextUtils.isEmpty(packageName)) {
- return AngleDriverChoice.DEFAULT;
+ return false;
}
// Check the semi-global switch (i.e. once system has booted enough) for whether ANGLE
@@ -452,7 +442,7 @@ public class GraphicsEnvironment {
}
if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) {
Log.v(TAG, "Turn on ANGLE for all applications.");
- return AngleDriverChoice.ANGLE;
+ return true;
}
// Get the per-application settings lists
@@ -475,7 +465,7 @@ public class GraphicsEnvironment {
+ optInPackages.size() + ", "
+ "number of values: "
+ optInValues.size());
- return mEnabledByGameMode ? AngleDriverChoice.ANGLE : AngleDriverChoice.DEFAULT;
+ return mEnabledByGameMode;
}
// See if this application is listed in the per-application settings list
@@ -483,7 +473,7 @@ public class GraphicsEnvironment {
if (pkgIndex < 0) {
Log.v(TAG, packageName + " is not listed in per-application setting");
- return mEnabledByGameMode ? AngleDriverChoice.ANGLE : AngleDriverChoice.DEFAULT;
+ return mEnabledByGameMode;
}
mAngleOptInIndex = pkgIndex;
@@ -493,14 +483,14 @@ public class GraphicsEnvironment {
Log.v(TAG,
"ANGLE Developer option for '" + packageName + "' "
+ "set to: '" + optInValue + "'");
- if (optInValue.equals(AngleDriverChoice.ANGLE.choice)) {
- return AngleDriverChoice.ANGLE;
- } else if (optInValue.equals(AngleDriverChoice.NATIVE.choice)) {
- return AngleDriverChoice.NATIVE;
+ if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) {
+ return true;
+ } else if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)) {
+ return false;
} else {
// The user either chose default or an invalid value; go with the default driver or what
// the game mode indicates
- return mEnabledByGameMode ? AngleDriverChoice.ANGLE : AngleDriverChoice.DEFAULT;
+ return mEnabledByGameMode;
}
}
@@ -568,13 +558,7 @@ public class GraphicsEnvironment {
private boolean setupAngle(Context context, Bundle bundle, PackageManager packageManager,
String packageName) {
- final AngleDriverChoice angleDriverChoice = queryAngleChoice(context, bundle, packageName);
- if (angleDriverChoice == AngleDriverChoice.DEFAULT) {
- return false;
- }
-
- if (queryAngleChoice(context, bundle, packageName) == AngleDriverChoice.NATIVE) {
- nativeSetAngleInfo("", true, packageName, null);
+ if (!shouldUseAngle(context, bundle, packageName)) {
return false;
}
@@ -643,10 +627,10 @@ public class GraphicsEnvironment {
Log.d(TAG, "ANGLE package libs: " + paths);
}
- // If we make it to here, ANGLE apk will be used. Call nativeSetAngleInfo() with the
- // application package name and ANGLE features to use.
+ // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name,
+ // and features to use.
final String[] features = getAngleEglFeatures(context, bundle);
- nativeSetAngleInfo(paths, false, packageName, features);
+ setAngleInfo(paths, false, packageName, features);
return true;
}
@@ -668,10 +652,10 @@ public class GraphicsEnvironment {
return false;
}
- // If we make it to here, system ANGLE will be used. Call nativeSetAngleInfo() with
- // the application package name and ANGLE features to use.
+ // If we make it to here, ANGLE will be used. Call setAngleInfo() with the package name,
+ // and features to use.
final String[] features = getAngleEglFeatures(context, bundle);
- nativeSetAngleInfo("system", false, packageName, features);
+ setAngleInfo("", true, packageName, features);
return true;
}
@@ -952,8 +936,8 @@ public class GraphicsEnvironment {
private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
long driverVersionCode, long driverBuildTime, String appPackageName, int vulkanVersion);
- private static native void nativeSetAngleInfo(String path, boolean useNativeDriver,
- String packageName, String[] features);
+ private static native void setAngleInfo(String path, boolean useSystemAngle, String packageName,
+ String[] features);
private static native boolean setInjectLayersPrSetDumpable();
private static native void nativeToggleAngleAsSystemDriver(boolean enabled);
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
index 467daa028afd..ce2c18080b91 100644
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
@@ -295,8 +295,8 @@ final class IInputMethodManagerGlobalInvoker {
@AnyThread
static boolean showSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
- @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
- int lastClickToolType, @Nullable ResultReceiver resultReceiver,
+ @Nullable ImeTracker.Token statsToken, int flags, int lastClickToolType,
+ @Nullable ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
final IInputMethodManager service = getService();
if (service == null) {
@@ -312,7 +312,7 @@ final class IInputMethodManagerGlobalInvoker {
@AnyThread
static boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
- @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
+ @Nullable ImeTracker.Token statsToken, int flags,
@Nullable ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
final IInputMethodManager service = getService();
if (service == null) {
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index 9340f46b257f..92380ed7a7bc 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -17,7 +17,6 @@
package android.view.inputmethod;
import android.annotation.DurationMillisLong;
-import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -37,8 +36,6 @@ import com.android.internal.inputmethod.IInputMethod;
import com.android.internal.inputmethod.InlineSuggestionsRequestInfo;
import com.android.internal.inputmethod.InputMethodNavButtonFlags;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
@@ -272,14 +269,6 @@ public interface InputMethod {
*/
@MainThread
public void revokeSession(InputMethodSession session);
-
- /** @hide */
- @IntDef(flag = true, prefix = { "SHOW_" }, value = {
- SHOW_EXPLICIT,
- SHOW_FORCED,
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface ShowFlags {}
/**
* Flag for {@link #showSoftInput}: this show has been explicitly
@@ -299,6 +288,8 @@ public interface InputMethod {
/**
* Request that any soft input part of the input method be shown to the user.
*
+ * @param flags Provides additional information about the show request.
+ * Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
* @param resultReceiver The client requesting the show may wish to
* be told the impact of their request, which should be supplied here.
* The result code should be
@@ -313,7 +304,7 @@ public interface InputMethod {
* @hide
*/
@MainThread
- public default void showSoftInputWithToken(@ShowFlags int flags, ResultReceiver resultReceiver,
+ public default void showSoftInputWithToken(int flags, ResultReceiver resultReceiver,
IBinder showInputToken, @Nullable ImeTracker.Token statsToken) {
showSoftInput(flags, resultReceiver);
}
@@ -321,6 +312,8 @@ public interface InputMethod {
/**
* Request that any soft input part of the input method be shown to the user.
*
+ * @param flags Provides additional information about the show request.
+ * Currently may be 0 or have the bit {@link #SHOW_EXPLICIT} set.
* @param resultReceiver The client requesting the show may wish to
* be told the impact of their request, which should be supplied here.
* The result code should be
@@ -330,12 +323,11 @@ public interface InputMethod {
* {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
*/
@MainThread
- public void showSoftInput(@ShowFlags int flags, ResultReceiver resultReceiver);
+ public void showSoftInput(int flags, ResultReceiver resultReceiver);
/**
* Request that any soft input part of the input method be hidden from the user.
- *
- * @param flags Provides additional information about the hide request.
+ * @param flags Provides additional information about the show request.
* Currently always 0.
* @param resultReceiver The client requesting the show may wish to
* be told the impact of their request, which should be supplied here.
@@ -358,8 +350,7 @@ public interface InputMethod {
/**
* Request that any soft input part of the input method be hidden from the user.
- *
- * @param flags Provides additional information about the hide request.
+ * @param flags Provides additional information about the show request.
* Currently always 0.
* @param resultReceiver The client requesting the show may wish to
* be told the impact of their request, which should be supplied here.
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 52b7d1d41727..3f308e6fccee 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -39,7 +39,6 @@ import android.Manifest;
import android.annotation.DisplayContext;
import android.annotation.DrawableRes;
import android.annotation.DurationMillisLong;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
@@ -122,8 +121,6 @@ import com.android.internal.view.IInputMethodManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
@@ -2007,14 +2004,6 @@ public final class InputMethodManager {
}
}
- /** @hide */
- @IntDef(flag = true, prefix = { "SHOW_" }, value = {
- SHOW_IMPLICIT,
- SHOW_FORCED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ShowFlags {}
-
/**
* Flag for {@link #showSoftInput} to indicate that this is an implicit
* request to show the input window, not as the result of a direct request
@@ -2046,8 +2035,10 @@ public final class InputMethodManager {
* {@link View#isFocused view focus}, and its containing window has
* {@link View#hasWindowFocus window focus}. Otherwise the call fails and
* returns {@code false}.
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link #SHOW_IMPLICIT} bit set.
*/
- public boolean showSoftInput(View view, @ShowFlags int flags) {
+ public boolean showSoftInput(View view, int flags) {
// Re-dispatch if there is a context mismatch.
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
if (fallbackImm != null) {
@@ -2110,20 +2101,21 @@ public final class InputMethodManager {
* {@link View#isFocused view focus}, and its containing window has
* {@link View#hasWindowFocus window focus}. Otherwise the call fails and
* returns {@code false}.
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link #SHOW_IMPLICIT} bit set.
* @param resultReceiver If non-null, this will be called by the IME when
* it has processed your request to tell you what it has done. The result
* code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
* {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
* {@link #RESULT_HIDDEN}.
*/
- public boolean showSoftInput(View view, @ShowFlags int flags, ResultReceiver resultReceiver) {
+ public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
return showSoftInput(view, null /* statsToken */, flags, resultReceiver,
SoftInputShowHideReason.SHOW_SOFT_INPUT);
}
- private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken,
- @ShowFlags int flags, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken, int flags,
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
if (statsToken == null) {
statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, reason);
@@ -2177,7 +2169,7 @@ public final class InputMethodManager {
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
- public void showSoftInputUnchecked(@ShowFlags int flags, ResultReceiver resultReceiver) {
+ public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
synchronized (mH) {
final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestShow(
null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
@@ -2208,14 +2200,6 @@ public final class InputMethodManager {
}
}
- /** @hide */
- @IntDef(flag = true, prefix = { "HIDE_" }, value = {
- HIDE_IMPLICIT_ONLY,
- HIDE_NOT_ALWAYS,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface HideFlags {}
-
/**
* Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
* to indicate that the soft input window should only be hidden if it was not explicitly shown
@@ -2237,8 +2221,10 @@ public final class InputMethodManager {
*
* @param windowToken The token of the window that is making the request,
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
*/
- public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags) {
+ public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
return hideSoftInputFromWindow(windowToken, flags, null);
}
@@ -2260,19 +2246,21 @@ public final class InputMethodManager {
*
* @param windowToken The token of the window that is making the request,
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
* @param resultReceiver If non-null, this will be called by the IME when
* it has processed your request to tell you what it has done. The result
* code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
* {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
* {@link #RESULT_HIDDEN}.
*/
- public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags,
+ public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
return hideSoftInputFromWindow(windowToken, flags, resultReceiver,
SoftInputShowHideReason.HIDE_SOFT_INPUT);
}
- private boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags,
+ private boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
null /* component */, Process.myUid(),
@@ -2475,6 +2463,12 @@ public final class InputMethodManager {
* If not the input window will be displayed.
* @param windowToken The token of the window that is making the request,
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
+ * @param showFlags Provides additional operating flags. May be
+ * 0 or have the {@link #SHOW_IMPLICIT},
+ * {@link #SHOW_FORCED} bit set.
+ * @param hideFlags Provides additional operating flags. May be
+ * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
+ * {@link #HIDE_NOT_ALWAYS} bit set.
*
* @deprecated Use {@link #showSoftInput(View, int)} or
* {@link #hideSoftInputFromWindow(IBinder, int)} explicitly instead.
@@ -2483,8 +2477,7 @@ public final class InputMethodManager {
* has an effect if the calling app is the current IME focus.
*/
@Deprecated
- public void toggleSoftInputFromWindow(IBinder windowToken, @ShowFlags int showFlags,
- @HideFlags int hideFlags) {
+ public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
ImeTracing.getInstance().triggerClientDump(
"InputMethodManager#toggleSoftInputFromWindow", InputMethodManager.this,
null /* icProto */);
@@ -2502,6 +2495,12 @@ public final class InputMethodManager {
*
* If the input window is already displayed, it gets hidden.
* If not the input window will be displayed.
+ * @param showFlags Provides additional operating flags. May be
+ * 0 or have the {@link #SHOW_IMPLICIT},
+ * {@link #SHOW_FORCED} bit set.
+ * @param hideFlags Provides additional operating flags. May be
+ * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
+ * {@link #HIDE_NOT_ALWAYS} bit set.
*
* @deprecated Use {@link #showSoftInput(View, int)} or
* {@link #hideSoftInputFromWindow(IBinder, int)} explicitly instead.
@@ -2510,7 +2509,7 @@ public final class InputMethodManager {
* has an effect if the calling app is the current IME focus.
*/
@Deprecated
- public void toggleSoftInput(@ShowFlags int showFlags, @HideFlags int hideFlags) {
+ public void toggleSoftInput(int showFlags, int hideFlags) {
ImeTracing.getInstance().triggerClientDump(
"InputMethodManager#toggleSoftInput", InputMethodManager.this,
null /* icProto */);
@@ -3523,12 +3522,15 @@ public final class InputMethodManager {
* @param token Supplies the identifying token given to an input method
* when it was started, which allows it to perform this operation on
* itself.
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
+ * {@link #HIDE_NOT_ALWAYS} bit set.
* @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
* intended for IME developers who should be accessing APIs through the service. APIs in this
* class are intended for app developers interacting with the IME.
*/
@Deprecated
- public void hideSoftInputFromInputMethod(IBinder token, @HideFlags int flags) {
+ public void hideSoftInputFromInputMethod(IBinder token, int flags) {
InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(
flags, SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION);
}
@@ -3542,12 +3544,15 @@ public final class InputMethodManager {
* @param token Supplies the identifying token given to an input method
* when it was started, which allows it to perform this operation on
* itself.
+ * @param flags Provides additional operating flags. Currently may be
+ * 0 or have the {@link #SHOW_IMPLICIT} or
+ * {@link #SHOW_FORCED} bit set.
* @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
* intended for IME developers who should be accessing APIs through the service. APIs in this
* class are intended for app developers interacting with the IME.
*/
@Deprecated
- public void showSoftInputFromInputMethod(IBinder token, @ShowFlags int flags) {
+ public void showSoftInputFromInputMethod(IBinder token, int flags) {
InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
}
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index 4f48cb684e8c..af6af14472db 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -169,6 +169,12 @@ public interface InputMethodSession {
/**
* Toggle the soft input window.
* Applications can toggle the state of the soft input window.
+ * @param showFlags Provides additional operating flags. May be
+ * 0 or have the {@link InputMethodManager#SHOW_IMPLICIT},
+ * {@link InputMethodManager#SHOW_FORCED} bit set.
+ * @param hideFlags Provides additional operating flags. May be
+ * 0 or have the {@link InputMethodManager#HIDE_IMPLICIT_ONLY},
+ * {@link InputMethodManager#HIDE_NOT_ALWAYS} bit set.
*
* @deprecated Starting in {@link android.os.Build.VERSION_CODES#S} the system no longer invokes
* this method, instead it explicitly shows or hides the IME. An {@code InputMethodService}
@@ -176,8 +182,7 @@ public interface InputMethodSession {
* InputMethodService#requestShowSelf} or {@link InputMethodService#requestHideSelf}
*/
@Deprecated
- public void toggleSoftInput(@InputMethodManager.ShowFlags int showFlags,
- @InputMethodManager.HideFlags int hideFlags);
+ public void toggleSoftInput(int showFlags, int hideFlags);
/**
* This method is called when the cursor and/or the character position relevant to text input
diff --git a/core/java/com/android/internal/flags/CoreFlags.java b/core/java/com/android/internal/flags/CoreFlags.java
deleted file mode 100644
index f177ef88c38f..000000000000
--- a/core/java/com/android/internal/flags/CoreFlags.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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 com.android.internal.flags;
-
-import android.flags.BooleanFlag;
-import android.flags.DynamicBooleanFlag;
-import android.flags.FeatureFlags;
-import android.flags.FusedOffFlag;
-import android.flags.FusedOnFlag;
-import android.flags.SyncableFlag;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Flags defined here are can be read by code in core.
- *
- * Flags not defined here will throw a security exception if third-party processes attempts to read
- * them.
- *
- * DO NOT define a flag here unless you explicitly intend for that flag to be readable by code that
- * runs inside a third party process.
- */
-public abstract class CoreFlags {
- private static final List<SyncableFlag> sKnownFlags = new ArrayList<>();
-
- public static BooleanFlag BOOL_FLAG = booleanFlag("core", "bool_flag", false);
- public static FusedOffFlag OFF_FLAG = fusedOffFlag("core", "off_flag");
- public static FusedOnFlag ON_FLAG = fusedOnFlag("core", "on_flag");
- public static DynamicBooleanFlag DYN_FLAG = dynamicBooleanFlag("core", "dyn_flag", true);
-
- /** Returns true if the passed in flag matches a flag in this class. */
- public static boolean isCoreFlag(SyncableFlag flag) {
- for (SyncableFlag knownFlag : sKnownFlags) {
- if (knownFlag.getName().equals(flag.getName())
- && knownFlag.getNamespace().equals(flag.getNamespace())) {
- return true;
- }
- }
- return false;
- }
-
- public static List<SyncableFlag> getCoreFlags() {
- return sKnownFlags;
- }
-
- private static BooleanFlag booleanFlag(String namespace, String name, boolean defaultValue) {
- BooleanFlag f = FeatureFlags.booleanFlag(namespace, name, defaultValue);
-
- sKnownFlags.add(new SyncableFlag(namespace, name, Boolean.toString(defaultValue), false));
-
- return f;
- }
-
- private static FusedOffFlag fusedOffFlag(String namespace, String name) {
- FusedOffFlag f = FeatureFlags.fusedOffFlag(namespace, name);
-
- sKnownFlags.add(new SyncableFlag(namespace, name, "false", false));
-
- return f;
- }
-
- private static FusedOnFlag fusedOnFlag(String namespace, String name) {
- FusedOnFlag f = FeatureFlags.fusedOnFlag(namespace, name);
-
- sKnownFlags.add(new SyncableFlag(namespace, name, "true", false));
-
- return f;
- }
-
- private static DynamicBooleanFlag dynamicBooleanFlag(
- String namespace, String name, boolean defaultValue) {
- DynamicBooleanFlag f = FeatureFlags.dynamicBooleanFlag(namespace, name, defaultValue);
-
- sKnownFlags.add(new SyncableFlag(namespace, name, Boolean.toString(defaultValue), true));
-
- return f;
- }
-}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 8a5c7ef18621..66e3333acf7c 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -26,7 +26,6 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.ImeTracker;
-import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.GuardedBy;
@@ -254,11 +253,13 @@ public final class InputMethodPrivilegedOperations {
/**
* Calls {@link IInputMethodPrivilegedOperations#hideMySoftInput(int, int, AndroidFuture)}
*
+ * @param flags additional operating flags
* @param reason the reason to hide soft input
+ * @see android.view.inputmethod.InputMethodManager#HIDE_IMPLICIT_ONLY
+ * @see android.view.inputmethod.InputMethodManager#HIDE_NOT_ALWAYS
*/
@AnyThread
- public void hideMySoftInput(@InputMethodManager.HideFlags int flags,
- @SoftInputShowHideReason int reason) {
+ public void hideMySoftInput(int flags, @SoftInputShowHideReason int reason) {
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
if (ops == null) {
return;
@@ -274,9 +275,13 @@ public final class InputMethodPrivilegedOperations {
/**
* Calls {@link IInputMethodPrivilegedOperations#showMySoftInput(int, AndroidFuture)}
+ *
+ * @param flags additional operating flags
+ * @see android.view.inputmethod.InputMethodManager#SHOW_IMPLICIT
+ * @see android.view.inputmethod.InputMethodManager#SHOW_FORCED
*/
@AnyThread
- public void showMySoftInput(@InputMethodManager.ShowFlags int flags) {
+ public void showMySoftInput(int flags) {
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
if (ops == null) {
return;
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 8fc30d1c248d..afc3cbd15f88 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -50,7 +50,7 @@ void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
appPackageNameChars.c_str(), vulkanVersion);
}
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useNativeDriver,
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useSystemAngle,
jstring packageName, jobjectArray featuresObj) {
ScopedUtfChars pathChars(env, path);
ScopedUtfChars packageNameChars(env, packageName);
@@ -73,7 +73,7 @@ void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jboolean useN
}
}
- android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), useNativeDriver,
+ android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), useSystemAngle,
packageNameChars.c_str(), features);
}
@@ -118,7 +118,7 @@ const JNINativeMethod g_methods[] = {
reinterpret_cast<void*>(setGpuStats_native)},
{"setInjectLayersPrSetDumpable", "()Z",
reinterpret_cast<void*>(setInjectLayersPrSetDumpable_native)},
- {"nativeSetAngleInfo", "(Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V",
+ {"setAngleInfo", "(Ljava/lang/String;ZLjava/lang/String;[Ljava/lang/String;)V",
reinterpret_cast<void*>(setAngleInfo_native)},
{"setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V",
reinterpret_cast<void*>(setLayerPaths_native)},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 10cf353bf5e9..a01c7b6355c1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7655,24 +7655,6 @@
<permission android:name="android.permission.GET_ANY_PROVIDER_TYPE"
android:protectionLevel="signature" />
-
- <!-- @hide Allows internal applications to read and synchronize non-core flags.
- Apps without this permission can only read a subset of flags specifically intended
- for use in "core", (i.e. third party apps). Apps with this permission can define their
- own flags, and federate those values with other system-level apps.
- <p>Not for use by third-party applications.
- <p>Protection level: signature
- -->
- <permission android:name="android.permission.SYNC_FLAGS"
- android:protectionLevel="signature" />
-
- <!-- @hide Allows internal applications to override flags in the FeatureFlags service.
- <p>Not for use by third-party applications.
- <p>Protection level: signature
- -->
- <permission android:name="android.permission.WRITE_FLAGS"
- android:protectionLevel="signature" />
-
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/core/tests/coretests/src/android/flags/FeatureFlagsTest.java b/core/tests/coretests/src/android/flags/FeatureFlagsTest.java
deleted file mode 100644
index 3fc94394d12c..000000000000
--- a/core/tests/coretests/src/android/flags/FeatureFlagsTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.flags;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-
-@SmallTest
-@Presubmit
-public class FeatureFlagsTest {
-
- IFeatureFlagsFake mIFeatureFlagsFake = new IFeatureFlagsFake();
- FeatureFlags mFeatureFlags = new FeatureFlags(mIFeatureFlagsFake);
-
- @Before
- public void setup() {
- FeatureFlags.setInstance(mFeatureFlags);
- }
-
- @Test
- public void testFusedOff_Disabled() {
- FusedOffFlag flag = FeatureFlags.fusedOffFlag("test", "a");
- assertThat(mFeatureFlags.isEnabled(flag)).isFalse();
- }
-
- @Test
- public void testFusedOn_Enabled() {
- FusedOnFlag flag = FeatureFlags.fusedOnFlag("test", "a");
- assertThat(mFeatureFlags.isEnabled(flag)).isTrue();
- }
-
- @Test
- public void testBooleanFlag_DefaultDisabled() {
- BooleanFlag flag = FeatureFlags.booleanFlag("test", "a", false);
- assertThat(mFeatureFlags.isEnabled(flag)).isFalse();
- }
-
- @Test
- public void testBooleanFlag_DefaultEnabled() {
- BooleanFlag flag = FeatureFlags.booleanFlag("test", "a", true);
- assertThat(mFeatureFlags.isEnabled(flag)).isTrue();
- }
-
- @Test
- public void testDynamicBooleanFlag_DefaultDisabled() {
- DynamicBooleanFlag flag = FeatureFlags.dynamicBooleanFlag("test", "a", false);
- assertThat(mFeatureFlags.isCurrentlyEnabled(flag)).isFalse();
- }
-
- @Test
- public void testDynamicBooleanFlag_DefaultEnabled() {
- DynamicBooleanFlag flag = FeatureFlags.dynamicBooleanFlag("test", "a", true);
- assertThat(mFeatureFlags.isCurrentlyEnabled(flag)).isTrue();
- }
-
- @Test
- public void testBooleanFlag_OverrideBeforeRead() {
- BooleanFlag flag = FeatureFlags.booleanFlag("test", "a", false);
- SyncableFlag syncableFlag = new SyncableFlag(
- flag.getNamespace(), flag.getName(), "true", false);
-
- mIFeatureFlagsFake.setFlagOverrides(List.of(syncableFlag));
-
- assertThat(mFeatureFlags.isEnabled(flag)).isTrue();
- }
-
- @Test
- public void testFusedOffFlag_OverrideHasNoEffect() {
- FusedOffFlag flag = FeatureFlags.fusedOffFlag("test", "a");
- SyncableFlag syncableFlag = new SyncableFlag(
- flag.getNamespace(), flag.getName(), "true", false);
-
- mIFeatureFlagsFake.setFlagOverrides(List.of(syncableFlag));
-
- assertThat(mFeatureFlags.isEnabled(flag)).isFalse();
- }
-
- @Test
- public void testFusedOnFlag_OverrideHasNoEffect() {
- FusedOnFlag flag = FeatureFlags.fusedOnFlag("test", "a");
- SyncableFlag syncableFlag = new SyncableFlag(
- flag.getNamespace(), flag.getName(), "false", false);
-
- mIFeatureFlagsFake.setFlagOverrides(List.of(syncableFlag));
-
- assertThat(mFeatureFlags.isEnabled(flag)).isTrue();
- }
-
- @Test
- public void testDynamicFlag_OverrideBeforeRead() {
- DynamicBooleanFlag flag = FeatureFlags.dynamicBooleanFlag("test", "a", false);
- SyncableFlag syncableFlag = new SyncableFlag(
- flag.getNamespace(), flag.getName(), "true", true);
-
- mIFeatureFlagsFake.setFlagOverrides(List.of(syncableFlag));
-
- // Changes to true
- assertThat(mFeatureFlags.isCurrentlyEnabled(flag)).isTrue();
- }
-
- @Test
- public void testDynamicFlag_OverrideAfterRead() {
- DynamicBooleanFlag flag = FeatureFlags.dynamicBooleanFlag("test", "a", false);
- SyncableFlag syncableFlag = new SyncableFlag(
- flag.getNamespace(), flag.getName(), "true", true);
-
- // Starts false
- assertThat(mFeatureFlags.isCurrentlyEnabled(flag)).isFalse();
-
- mIFeatureFlagsFake.setFlagOverrides(List.of(syncableFlag));
-
- // Changes to true
- assertThat(mFeatureFlags.isCurrentlyEnabled(flag)).isTrue();
- }
-
- @Test
- public void testDynamicFlag_FiresListener() {
- DynamicBooleanFlag flag = FeatureFlags.dynamicBooleanFlag("test", "a", false);
- AtomicBoolean called = new AtomicBoolean(false);
- FeatureFlags.ChangeListener listener = flag1 -> called.set(true);
-
- mFeatureFlags.addChangeListener(listener);
-
- SyncableFlag syncableFlag = new SyncableFlag(
- flag.getNamespace(), flag.getName(), flag.getDefault().toString(), true);
-
- mIFeatureFlagsFake.setFlagOverrides(List.of(syncableFlag));
-
- // Fires listener.
- assertThat(called.get()).isTrue();
- }
-}
diff --git a/core/tests/coretests/src/android/flags/IFeatureFlagsFake.java b/core/tests/coretests/src/android/flags/IFeatureFlagsFake.java
deleted file mode 100644
index bc5d8aa3ac73..000000000000
--- a/core/tests/coretests/src/android/flags/IFeatureFlagsFake.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.flags;
-
-import android.os.IBinder;
-import android.os.RemoteException;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-class IFeatureFlagsFake implements IFeatureFlags {
-
- private final Set<IFeatureFlagsCallback> mCallbacks = new HashSet<>();
-
- List<SyncableFlag> mOverrides;
-
- @Override
- public IBinder asBinder() {
- return null;
- }
-
- @Override
- public List<SyncableFlag> syncFlags(List<SyncableFlag> flagList) {
- return mOverrides == null ? flagList : mOverrides;
- }
-
- @Override
- public List<SyncableFlag> queryFlags(List<SyncableFlag> flagList) {
- return mOverrides == null ? flagList : mOverrides; }
-
- @Override
- public void overrideFlag(SyncableFlag syncableFlag) {
- SyncableFlag match = findFlag(syncableFlag);
- if (match != null) {
- mOverrides.remove(match);
- }
-
- mOverrides.add(syncableFlag);
-
- for (IFeatureFlagsCallback cb : mCallbacks) {
- try {
- cb.onFlagChange(syncableFlag);
- } catch (RemoteException e) {
- // does not happen in fakes.
- }
- }
- }
-
- @Override
- public void resetFlag(SyncableFlag syncableFlag) {
- SyncableFlag match = findFlag(syncableFlag);
- if (match != null) {
- mOverrides.remove(match);
- }
-
- for (IFeatureFlagsCallback cb : mCallbacks) {
- try {
- cb.onFlagChange(syncableFlag);
- } catch (RemoteException e) {
- // does not happen in fakes.
- }
- }
- }
-
- private SyncableFlag findFlag(SyncableFlag syncableFlag) {
- SyncableFlag match = null;
- for (SyncableFlag sf : mOverrides) {
- if (sf.getName().equals(syncableFlag.getName())
- && sf.getNamespace().equals(syncableFlag.getNamespace())) {
- match = sf;
- break;
- }
- }
-
- return match;
- }
- @Override
- public void registerCallback(IFeatureFlagsCallback callback) {
- mCallbacks.add(callback);
- }
-
- @Override
- public void unregisterCallback(IFeatureFlagsCallback callback) {
- mCallbacks.remove(callback);
- }
-
- public void setFlagOverrides(List<SyncableFlag> flagList) {
- mOverrides = flagList;
- for (SyncableFlag sf : flagList) {
- for (IFeatureFlagsCallback cb : mCallbacks) {
- try {
- cb.onFlagChange(sf);
- } catch (RemoteException e) {
- // does not happen in fakes.
- }
- }
- }
- }
-}
diff --git a/packages/SystemUI/res/layout/status_bar_wifi_group.xml b/packages/SystemUI/res/layout/status_bar_wifi_group.xml
deleted file mode 100644
index 6cb6993bb762..000000000000
--- a/packages/SystemUI/res/layout/status_bar_wifi_group.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2018, 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.
-*/
--->
-<com.android.systemui.statusbar.StatusBarWifiView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/wifi_combo"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical" >
-
- <include layout="@layout/status_bar_wifi_group_inner" />
-
-</com.android.systemui.statusbar.StatusBarWifiView> \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 794e6941c2bb..b3e08c0bc69f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -165,15 +165,18 @@ public class KeyguardPinViewController
* Responsible for identifying if PIN hinting is to be enabled or not
*/
private boolean isPinHinting() {
- return mLockPatternUtils.getPinLength(KeyguardUpdateMonitor.getCurrentUser())
- == DEFAULT_PIN_LENGTH;
+ return mPinLength == DEFAULT_PIN_LENGTH;
}
/**
- * Responsible for identifying if auto confirm is enabled or not in Settings
+ * Responsible for identifying if auto confirm is enabled or not in Settings and
+ * a valid PIN_LENGTH is stored on the device (though the latter check is only to make it more
+ * robust since we only allow enabling PIN confirmation if the user has a valid PIN length
+ * saved on device)
*/
private boolean isAutoPinConfirmEnabledInSettings() {
//Checks if user has enabled the auto confirm in Settings
- return mLockPatternUtils.isAutoPinConfirmEnabled(KeyguardUpdateMonitor.getCurrentUser());
+ return mLockPatternUtils.isAutoPinConfirmEnabled(KeyguardUpdateMonitor.getCurrentUser())
+ && mPinLength != LockPatternUtils.PIN_LENGTH_UNAVAILABLE;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index 8b220242f7ad..6a5749cc5571 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -30,9 +30,8 @@ import android.view.View;
import androidx.annotation.NonNull;
+import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarLocation;
@@ -130,7 +129,6 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
TunerService tunerService,
@Main Handler mainHandler,
ContentResolver contentResolver,
- FeatureFlags featureFlags,
BatteryController batteryController) {
super(view);
mLocation = location;
@@ -142,7 +140,8 @@ public class BatteryMeterViewController extends ViewController<BatteryMeterView>
mBatteryController = batteryController;
mView.setBatteryEstimateFetcher(mBatteryController::getEstimatedTimeRemainingString);
- mView.setDisplayShieldEnabled(featureFlags.isEnabled(Flags.BATTERY_SHIELD_ICON));
+ mView.setDisplayShieldEnabled(
+ getContext().getResources().getBoolean(R.bool.flag_battery_shield_icon));
mSlotBattery = getResources().getString(com.android.internal.R.string.status_bar_battery);
mSettingObserver = new SettingObserver(mMainHandler);
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index f4da08d765c4..83c1c7100761 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -372,22 +372,10 @@ object Flags {
// TODO(b/256614753): Tracking Bug
val NEW_STATUS_BAR_MOBILE_ICONS = releasedFlag(606, "new_status_bar_mobile_icons")
- // TODO(b/256614210): Tracking Bug
- val NEW_STATUS_BAR_WIFI_ICON = releasedFlag(607, "new_status_bar_wifi_icon")
-
// TODO(b/256614751): Tracking Bug
val NEW_STATUS_BAR_MOBILE_ICONS_BACKEND =
unreleasedFlag(608, "new_status_bar_mobile_icons_backend", teamfood = true)
- // TODO(b/256613548): Tracking Bug
- val NEW_STATUS_BAR_WIFI_ICON_BACKEND =
- unreleasedFlag(609, "new_status_bar_wifi_icon_backend", teamfood = true)
-
- // TODO(b/256623670): Tracking Bug
- @JvmField
- val BATTERY_SHIELD_ICON =
- resourceBooleanFlag(610, R.bool.flag_battery_shield_icon, "battery_shield_icon")
-
// TODO(b/260881289): Tracking Bug
val NEW_STATUS_BAR_ICONS_DEBUG_COLORING =
unreleasedFlag(611, "new_status_bar_icons_debug_coloring")
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 023bfaa2997c..8ec8d115de78 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -282,7 +282,6 @@ abstract class ShadeModule {
tunerService: TunerService,
@Main mainHandler: Handler,
contentResolver: ContentResolver,
- featureFlags: FeatureFlags,
batteryController: BatteryController,
): BatteryMeterViewController {
return BatteryMeterViewController(
@@ -293,7 +292,6 @@ abstract class ShadeModule {
tunerService,
mainHandler,
contentResolver,
- featureFlags,
batteryController,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt
index ce730baeed0d..5d06f8d083d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarFrameLayout.kt
@@ -21,8 +21,8 @@ import android.widget.FrameLayout
/**
* A temporary base class that's shared between our old status bar connectivity view implementations
- * ([StatusBarWifiView], [StatusBarMobileView]) and our new status bar implementations (
- * [ModernStatusBarWifiView], [ModernStatusBarMobileView]).
+ * ([StatusBarMobileView]) and our new status bar implementations ([ModernStatusBarWifiView],
+ * [ModernStatusBarMobileView]).
*
* Once our refactor is over, we should be able to delete this go-between class and the old view
* class.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
deleted file mode 100644
index 8d7214d6bd75..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.systemui.statusbar;
-
-import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
-
-import java.util.ArrayList;
-
-/**
- * Start small: StatusBarWifiView will be able to layout from a WifiIconState
- */
-public class StatusBarWifiView extends BaseStatusBarFrameLayout implements DarkReceiver {
- private static final String TAG = "StatusBarWifiView";
-
- /// Used to show etc dots
- private StatusBarIconView mDotView;
- /// Contains the main icon layout
- private LinearLayout mWifiGroup;
- private ImageView mWifiIcon;
- private ImageView mIn;
- private ImageView mOut;
- private View mInoutContainer;
- private View mSignalSpacer;
- private View mAirplaneSpacer;
- private WifiIconState mState;
- private String mSlot;
- @StatusBarIconView.VisibleState
- private int mVisibleState = STATE_HIDDEN;
-
- public static StatusBarWifiView fromContext(Context context, String slot) {
- LayoutInflater inflater = LayoutInflater.from(context);
- StatusBarWifiView v = (StatusBarWifiView) inflater.inflate(R.layout.status_bar_wifi_group, null);
- v.setSlot(slot);
- v.init();
- v.setVisibleState(STATE_ICON);
- return v;
- }
-
- public StatusBarWifiView(Context context) {
- super(context);
- }
-
- public StatusBarWifiView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public StatusBarWifiView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public void setSlot(String slot) {
- mSlot = slot;
- }
-
- @Override
- public void setStaticDrawableColor(int color) {
- ColorStateList list = ColorStateList.valueOf(color);
- mWifiIcon.setImageTintList(list);
- mIn.setImageTintList(list);
- mOut.setImageTintList(list);
- mDotView.setDecorColor(color);
- }
-
- @Override
- public void setDecorColor(int color) {
- mDotView.setDecorColor(color);
- }
-
- @Override
- public String getSlot() {
- return mSlot;
- }
-
- @Override
- public boolean isIconVisible() {
- return mState != null && mState.visible;
- }
-
- @Override
- public void setVisibleState(@StatusBarIconView.VisibleState int state, boolean animate) {
- if (state == mVisibleState) {
- return;
- }
- mVisibleState = state;
-
- switch (state) {
- case STATE_ICON:
- mWifiGroup.setVisibility(View.VISIBLE);
- mDotView.setVisibility(View.GONE);
- break;
- case STATE_DOT:
- mWifiGroup.setVisibility(View.GONE);
- mDotView.setVisibility(View.VISIBLE);
- break;
- case STATE_HIDDEN:
- default:
- mWifiGroup.setVisibility(View.GONE);
- mDotView.setVisibility(View.GONE);
- break;
- }
- }
-
- @Override
- @StatusBarIconView.VisibleState
- public int getVisibleState() {
- return mVisibleState;
- }
-
- @Override
- public void getDrawingRect(Rect outRect) {
- super.getDrawingRect(outRect);
- float translationX = getTranslationX();
- float translationY = getTranslationY();
- outRect.left += translationX;
- outRect.right += translationX;
- outRect.top += translationY;
- outRect.bottom += translationY;
- }
-
- private void init() {
- mWifiGroup = findViewById(R.id.wifi_group);
- mWifiIcon = findViewById(R.id.wifi_signal);
- mIn = findViewById(R.id.wifi_in);
- mOut = findViewById(R.id.wifi_out);
- mSignalSpacer = findViewById(R.id.wifi_signal_spacer);
- mAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
- mInoutContainer = findViewById(R.id.inout_container);
-
- initDotView();
- }
-
- private void initDotView() {
- mDotView = new StatusBarIconView(mContext, mSlot, null);
- mDotView.setVisibleState(STATE_DOT);
-
- int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size_sp);
- LayoutParams lp = new LayoutParams(width, width);
- lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
- addView(mDotView, lp);
- }
-
- public void applyWifiState(WifiIconState state) {
- boolean requestLayout = false;
-
- if (state == null) {
- requestLayout = getVisibility() != View.GONE;
- setVisibility(View.GONE);
- mState = null;
- } else if (mState == null) {
- requestLayout = true;
- mState = state.copy();
- initViewState();
- } else if (!mState.equals(state)) {
- requestLayout = updateState(state.copy());
- }
-
- if (requestLayout) {
- requestLayout();
- }
- }
-
- private boolean updateState(WifiIconState state) {
- setContentDescription(state.contentDescription);
- if (mState.resId != state.resId && state.resId >= 0) {
- mWifiIcon.setImageDrawable(mContext.getDrawable(state.resId));
- }
-
- mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
- mOut.setVisibility(state.activityOut ? View.VISIBLE : View.GONE);
- mInoutContainer.setVisibility(
- (state.activityIn || state.activityOut) ? View.VISIBLE : View.GONE);
- mAirplaneSpacer.setVisibility(state.airplaneSpacerVisible ? View.VISIBLE : View.GONE);
- mSignalSpacer.setVisibility(state.signalSpacerVisible ? View.VISIBLE : View.GONE);
-
- boolean needsLayout = state.activityIn != mState.activityIn
- ||state.activityOut != mState.activityOut;
-
- if (mState.visible != state.visible) {
- needsLayout |= true;
- setVisibility(state.visible ? View.VISIBLE : View.GONE);
- }
-
- mState = state;
- return needsLayout;
- }
-
- private void initViewState() {
- setContentDescription(mState.contentDescription);
- if (mState.resId >= 0) {
- mWifiIcon.setImageDrawable(mContext.getDrawable(mState.resId));
- }
-
- mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
- mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE);
- mInoutContainer.setVisibility(
- (mState.activityIn || mState.activityOut) ? View.VISIBLE : View.GONE);
- mAirplaneSpacer.setVisibility(mState.airplaneSpacerVisible ? View.VISIBLE : View.GONE);
- mSignalSpacer.setVisibility(mState.signalSpacerVisible ? View.VISIBLE : View.GONE);
- setVisibility(mState.visible ? View.VISIBLE : View.GONE);
- }
-
- @Override
- public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
- int areaTint = getTint(areas, this, tint);
- ColorStateList color = ColorStateList.valueOf(areaTint);
- mWifiIcon.setImageTintList(color);
- mIn.setImageTintList(color);
- mOut.setImageTintList(color);
- mDotView.setDecorColor(areaTint);
- mDotView.setIconColor(areaTint, false);
- }
-
-
- @Override
- public String toString() {
- return "StatusBarWifiView(slot=" + mSlot + " state=" + mState + ")";
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 73f181b8c734..9aa28c31cfd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -18,10 +18,6 @@ package com.android.systemui.statusbar.connectivity;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
-import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.Nullable;
@@ -557,10 +553,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
mBroadcastDispatcher.unregisterReceiver(this);
}
- public int getConnectedWifiLevel() {
- return mWifiSignalController.getState().level;
- }
-
@Override
public AccessPointController getAccessPointController() {
return mAccessPoints;
@@ -654,14 +646,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
return mWifiSignalController.isCarrierMergedWifi(subId);
}
- boolean hasDefaultNetwork() {
- return !mNoDefaultNetwork;
- }
-
- boolean isNonCarrierWifiNetworkAvailable() {
- return !mNoNetworksAvailable;
- }
-
boolean isEthernetDefault() {
return mConnectedTransports.get(NetworkCapabilities.TRANSPORT_ETHERNET);
}
@@ -1242,15 +1226,12 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
private boolean mDemoInetCondition;
- private WifiState mDemoWifiState;
@Override
public void onDemoModeStarted() {
if (DEBUG) Log.d(TAG, "Entering demo mode");
unregisterListeners();
mDemoInetCondition = mInetCondition;
- mDemoWifiState = mWifiSignalController.getState();
- mDemoWifiState.ssid = "DemoMode";
}
@Override
@@ -1300,41 +1281,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
controller.updateConnectivity(connected, connected);
}
}
- String wifi = args.getString("wifi");
- if (wifi != null && !mStatusBarPipelineFlags.runNewWifiIconBackend()) {
- boolean show = wifi.equals("show");
- String level = args.getString("level");
- if (level != null) {
- mDemoWifiState.level = level.equals("null") ? -1
- : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
- mDemoWifiState.connected = mDemoWifiState.level >= 0;
- }
- String activity = args.getString("activity");
- if (activity != null) {
- switch (activity) {
- case "inout":
- mWifiSignalController.setActivity(DATA_ACTIVITY_INOUT);
- break;
- case "in":
- mWifiSignalController.setActivity(DATA_ACTIVITY_IN);
- break;
- case "out":
- mWifiSignalController.setActivity(DATA_ACTIVITY_OUT);
- break;
- default:
- mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
- break;
- }
- } else {
- mWifiSignalController.setActivity(DATA_ACTIVITY_NONE);
- }
- String ssid = args.getString("ssid");
- if (ssid != null) {
- mDemoWifiState.ssid = ssid;
- }
- mDemoWifiState.enabled = show;
- mWifiSignalController.notifyListeners();
- }
String sims = args.getString("sims");
if (sims != null && !mStatusBarPipelineFlags.useNewMobileIcons()) {
int num = MathUtils.constrain(Integer.parseInt(sims), 1, 8);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 39b5b5a4cef8..8e9f382d8c00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -35,11 +35,9 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
-import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
@@ -58,7 +56,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
private final ArrayList<ModernStatusBarMobileView> mModernMobileViews = new ArrayList<>();
private final int mIconSize;
- private StatusBarWifiView mWifiView;
private ModernStatusBarWifiView mModernWifiView;
private boolean mDemoMode;
private int mColor;
@@ -238,36 +235,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
addView(v, 0, createLayoutParams());
}
- public void addDemoWifiView(WifiIconState state) {
- Log.d(TAG, "addDemoWifiView: ");
- StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, state.slot);
-
- int viewIndex = getChildCount();
- // If we have mobile views, put wifi before them
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof StatusBarMobileView
- || child instanceof ModernStatusBarMobileView) {
- viewIndex = i;
- break;
- }
- }
-
- mWifiView = view;
- mWifiView.applyWifiState(state);
- mWifiView.setStaticDrawableColor(mColor);
- addView(view, viewIndex, createLayoutParams());
- }
-
- public void updateWifiState(WifiIconState state) {
- Log.d(TAG, "updateWifiState: ");
- if (mWifiView == null) {
- addDemoWifiView(state);
- } else {
- mWifiView.applyWifiState(state);
- }
- }
-
/**
* Add a new mobile icon view
*/
@@ -352,10 +319,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
public void onRemoveIcon(StatusIconDisplayable view) {
if (view.getSlot().equals("wifi")) {
- if (view instanceof StatusBarWifiView) {
- removeView(mWifiView);
- mWifiView = null;
- } else if (view instanceof ModernStatusBarWifiView) {
+ if (view instanceof ModernStatusBarWifiView) {
Log.d(TAG, "onRemoveIcon: removing modern wifi view");
removeView(mModernWifiView);
mModernWifiView = null;
@@ -409,9 +373,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
setColor(DarkIconDispatcher.getTint(areas, mStatusIcons, tint));
- if (mWifiView != null) {
- mWifiView.onDarkChanged(areas, darkIntensity, tint);
- }
if (mModernWifiView != null) {
mModernWifiView.onDarkChanged(areas, darkIntensity, tint);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 59583ddf3e34..42b0a4f13e0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -17,7 +17,6 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW;
import android.annotation.Nullable;
@@ -43,12 +42,10 @@ import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.BaseStatusBarFrameLayout;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
-import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
@@ -97,16 +94,9 @@ public interface StatusBarIconController {
*/
void setIcon(String slot, int resourceId, CharSequence contentDescription);
- /** */
- void setWifiIcon(String slot, WifiIconState state);
-
/**
* Sets up a wifi icon using the new data pipeline. No effect if the wifi icon has already been
* set up (inflated and added to the view hierarchy).
- *
- * This method completely replaces {@link #setWifiIcon} with the information from the new wifi
- * data pipeline. Icons will automatically keep their state up to date, so we don't have to
- * worry about funneling state objects through anymore.
*/
void setNewWifiIcon();
@@ -408,13 +398,7 @@ public interface StatusBarIconController {
mMobileIconsViewModel = null;
}
- if (statusBarPipelineFlags.runNewWifiIconBackend()) {
- // This starts the flow for the new pipeline, and will notify us of changes if
- // {@link StatusBarPipelineFlags#useNewWifiIcon} is also true.
- mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
- } else {
- mWifiViewModel = null;
- }
+ mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
}
public boolean isDemoable() {
@@ -462,9 +446,6 @@ public interface StatusBarIconController {
case TYPE_ICON:
return addIcon(index, slot, blocked, holder.getIcon());
- case TYPE_WIFI:
- return addWifiIcon(index, slot, holder.getWifiState());
-
case TYPE_WIFI_NEW:
return addNewWifiIcon(index, slot);
@@ -487,29 +468,7 @@ public interface StatusBarIconController {
return view;
}
- @VisibleForTesting
- protected StatusIconDisplayable addWifiIcon(int index, String slot, WifiIconState state) {
- if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- throw new IllegalStateException("Attempting to add a wifi icon while the new "
- + "icons are enabled is not supported");
- }
-
- final StatusBarWifiView view = onCreateStatusBarWifiView(slot);
- view.applyWifiState(state);
- mGroup.addView(view, index, onCreateLayoutParams());
-
- if (mIsInDemoMode) {
- mDemoStatusIcons.addDemoWifiView(state);
- }
- return view;
- }
-
protected StatusIconDisplayable addNewWifiIcon(int index, String slot) {
- if (!mStatusBarPipelineFlags.useNewWifiIcon()) {
- throw new IllegalStateException("Attempting to add a wifi icon using the new"
- + "pipeline, but the enabled flag is false.");
- }
-
ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
mGroup.addView(view, index, onCreateLayoutParams());
@@ -573,11 +532,6 @@ public interface StatusBarIconController {
return new StatusBarIconView(mContext, slot, null, blocked);
}
- private StatusBarWifiView onCreateStatusBarWifiView(String slot) {
- StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, slot);
- return view;
- }
-
private ModernStatusBarWifiView onCreateModernStatusBarWifiView(String slot) {
return ModernStatusBarWifiView.constructAndBind(mContext, slot, mWifiViewModel);
}
@@ -640,9 +594,6 @@ public interface StatusBarIconController {
case TYPE_ICON:
onSetIcon(viewIndex, holder.getIcon());
return;
- case TYPE_WIFI:
- onSetWifiIcon(viewIndex, holder.getWifiState());
- return;
case TYPE_MOBILE:
onSetMobileIcon(viewIndex, holder.getMobileState());
return;
@@ -655,23 +606,6 @@ public interface StatusBarIconController {
}
}
- public void onSetWifiIcon(int viewIndex, WifiIconState state) {
- View view = mGroup.getChildAt(viewIndex);
- if (view instanceof StatusBarWifiView) {
- ((StatusBarWifiView) view).applyWifiState(state);
- } else if (view instanceof ModernStatusBarWifiView) {
- // ModernStatusBarWifiView will automatically apply state based on its callbacks, so
- // we don't need to call applyWifiState.
- } else {
- throw new IllegalStateException("View at " + viewIndex + " must be of type "
- + "StatusBarWifiView or ModernStatusBarWifiView");
- }
-
- if (mIsInDemoMode) {
- mDemoStatusIcons.updateWifiState(state);
- }
- }
-
public void onSetMobileIcon(int viewIndex, MobileIconState state) {
View view = mGroup.getChildAt(viewIndex);
if (view instanceof StatusBarMobileView) {
@@ -703,9 +637,7 @@ public interface StatusBarIconController {
mIsInDemoMode = true;
if (mDemoStatusIcons == null) {
mDemoStatusIcons = createDemoStatusIcons();
- if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- mDemoStatusIcons.addModernWifiView(mWifiViewModel);
- }
+ mDemoStatusIcons.addModernWifiView(mWifiViewModel);
}
mDemoStatusIcons.onDemoModeStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 80d5651a65dc..d1a02d6cd611 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -40,7 +40,6 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -202,35 +201,7 @@ public class StatusBarIconControllerImpl implements Tunable,
}
@Override
- public void setWifiIcon(String slot, WifiIconState state) {
- if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- Log.d(TAG, "ignoring old pipeline callback because the new wifi icon is enabled");
- return;
- }
-
- if (state == null) {
- removeIcon(slot, 0);
- return;
- }
-
- StatusBarIconHolder holder = mStatusBarIconList.getIconHolder(slot, 0);
- if (holder == null) {
- holder = StatusBarIconHolder.fromWifiIconState(state);
- setIcon(slot, holder);
- } else {
- holder.setWifiState(state);
- handleSet(slot, holder);
- }
- }
-
-
- @Override
public void setNewWifiIcon() {
- if (!mStatusBarPipelineFlags.useNewWifiIcon()) {
- Log.d(TAG, "ignoring new pipeline callback because the new wifi icon is disabled");
- return;
- }
-
String slot = mContext.getString(com.android.internal.R.string.status_bar_wifi);
StatusBarIconHolder holder = mStatusBarIconList.getIconHolder(slot, /* tag= */ 0);
if (holder == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index 833cb93f62e9..01fd247f54bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -25,7 +25,6 @@ import android.os.UserHandle;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel;
import java.lang.annotation.Retention;
@@ -36,7 +35,6 @@ import java.lang.annotation.RetentionPolicy;
*/
public class StatusBarIconHolder {
public static final int TYPE_ICON = 0;
- public static final int TYPE_WIFI = 1;
public static final int TYPE_MOBILE = 2;
/**
* TODO (b/249790733): address this once the new pipeline is in place
@@ -65,7 +63,6 @@ public class StatusBarIconHolder {
@IntDef({
TYPE_ICON,
- TYPE_WIFI,
TYPE_MOBILE,
TYPE_MOBILE_NEW,
TYPE_WIFI_NEW
@@ -74,7 +71,6 @@ public class StatusBarIconHolder {
@interface IconType {}
private StatusBarIcon mIcon;
- private WifiIconState mWifiState;
private MobileIconState mMobileState;
private @IconType int mType = TYPE_ICON;
private int mTag = 0;
@@ -83,7 +79,6 @@ public class StatusBarIconHolder {
public static String getTypeString(@IconType int type) {
switch(type) {
case TYPE_ICON: return "ICON";
- case TYPE_WIFI: return "WIFI_OLD";
case TYPE_MOBILE: return "MOBILE_OLD";
case TYPE_MOBILE_NEW: return "MOBILE_NEW";
case TYPE_WIFI_NEW: return "WIFI_NEW";
@@ -101,25 +96,6 @@ public class StatusBarIconHolder {
return wrapper;
}
- /** */
- public static StatusBarIconHolder fromResId(
- Context context,
- int resId,
- CharSequence contentDescription) {
- StatusBarIconHolder holder = new StatusBarIconHolder();
- holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
- Icon.createWithResource( context, resId), 0, 0, contentDescription);
- return holder;
- }
-
- /** */
- public static StatusBarIconHolder fromWifiIconState(WifiIconState state) {
- StatusBarIconHolder holder = new StatusBarIconHolder();
- holder.mWifiState = state;
- holder.mType = TYPE_WIFI;
- return holder;
- }
-
/** Creates a new holder with for the new wifi icon. */
public static StatusBarIconHolder forNewWifiIcon() {
StatusBarIconHolder holder = new StatusBarIconHolder();
@@ -178,15 +154,6 @@ public class StatusBarIconHolder {
}
@Nullable
- public WifiIconState getWifiState() {
- return mWifiState;
- }
-
- public void setWifiState(WifiIconState state) {
- mWifiState = state;
- }
-
- @Nullable
public MobileIconState getMobileState() {
return mMobileState;
}
@@ -199,8 +166,6 @@ public class StatusBarIconHolder {
switch (mType) {
case TYPE_ICON:
return mIcon.visible;
- case TYPE_WIFI:
- return mWifiState.visible;
case TYPE_MOBILE:
return mMobileState.visible;
case TYPE_MOBILE_NEW:
@@ -223,10 +188,6 @@ public class StatusBarIconHolder {
mIcon.visible = visible;
break;
- case TYPE_WIFI:
- mWifiState.visible = visible;
- break;
-
case TYPE_MOBILE:
mMobileState.visible = visible;
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index d731f8886536..69199966dea6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -30,7 +30,6 @@ import com.android.systemui.statusbar.connectivity.IconState;
import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.SignalCallback;
-import com.android.systemui.statusbar.connectivity.WifiIndicators;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -51,7 +50,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
private final String mSlotAirplane;
private final String mSlotMobile;
- private final String mSlotWifi;
private final String mSlotEthernet;
private final String mSlotVpn;
private final String mSlotNoCalling;
@@ -67,17 +65,14 @@ public class StatusBarSignalPolicy implements SignalCallback,
private boolean mHideAirplane;
private boolean mHideMobile;
- private boolean mHideWifi;
private boolean mHideEthernet;
private boolean mActivityEnabled;
// Track as little state as possible, and only for padding purposes
private boolean mIsAirplaneMode = false;
- private boolean mIsWifiEnabled = false;
private ArrayList<MobileIconState> mMobileStates = new ArrayList<>();
private ArrayList<CallIndicatorIconState> mCallIndicatorStates = new ArrayList<>();
- private WifiIconState mWifiIconState = new WifiIconState();
private boolean mInitialized;
@Inject
@@ -99,7 +94,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane);
mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile);
- mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling);
@@ -154,15 +148,13 @@ public class StatusBarSignalPolicy implements SignalCallback,
ArraySet<String> hideList = StatusBarIconController.getIconHideList(mContext, newValue);
boolean hideAirplane = hideList.contains(mSlotAirplane);
boolean hideMobile = hideList.contains(mSlotMobile);
- boolean hideWifi = hideList.contains(mSlotWifi);
boolean hideEthernet = hideList.contains(mSlotEthernet);
if (hideAirplane != mHideAirplane || hideMobile != mHideMobile
- || hideEthernet != mHideEthernet || hideWifi != mHideWifi) {
+ || hideEthernet != mHideEthernet) {
mHideAirplane = hideAirplane;
mHideMobile = hideMobile;
mHideEthernet = hideEthernet;
- mHideWifi = hideWifi;
// Re-register to get new callbacks.
mNetworkController.removeCallback(this);
mNetworkController.addCallback(this);
@@ -170,56 +162,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
}
@Override
- public void setWifiIndicators(@NonNull WifiIndicators indicators) {
- if (DEBUG) {
- Log.d(TAG, "setWifiIndicators: " + indicators);
- }
- boolean visible = indicators.statusIcon.visible && !mHideWifi;
- boolean in = indicators.activityIn && mActivityEnabled && visible;
- boolean out = indicators.activityOut && mActivityEnabled && visible;
- mIsWifiEnabled = indicators.enabled;
-
- WifiIconState newState = mWifiIconState.copy();
-
- if (mWifiIconState.noDefaultNetwork && mWifiIconState.noNetworksAvailable
- && !mIsAirplaneMode) {
- newState.visible = true;
- newState.resId = R.drawable.ic_qs_no_internet_unavailable;
- } else if (mWifiIconState.noDefaultNetwork && !mWifiIconState.noNetworksAvailable
- && (!mIsAirplaneMode || (mIsAirplaneMode && mIsWifiEnabled))) {
- newState.visible = true;
- newState.resId = R.drawable.ic_qs_no_internet_available;
- } else {
- newState.visible = visible;
- newState.resId = indicators.statusIcon.icon;
- newState.activityIn = in;
- newState.activityOut = out;
- newState.contentDescription = indicators.statusIcon.contentDescription;
- MobileIconState first = getFirstMobileState();
- newState.signalSpacerVisible = first != null && first.typeId != 0;
- }
- newState.slot = mSlotWifi;
- newState.airplaneSpacerVisible = mIsAirplaneMode;
- updateWifiIconWithState(newState);
- mWifiIconState = newState;
- }
-
- private void updateShowWifiSignalSpacer(WifiIconState state) {
- MobileIconState first = getFirstMobileState();
- state.signalSpacerVisible = first != null && first.typeId != 0;
- }
-
- private void updateWifiIconWithState(WifiIconState state) {
- if (DEBUG) Log.d(TAG, "WifiIconState: " + state == null ? "" : state.toString());
- if (state.visible && state.resId > 0) {
- mIconController.setWifiIcon(mSlotWifi, state);
- mIconController.setIconVisibility(mSlotWifi, true);
- } else {
- mIconController.setIconVisibility(mSlotWifi, false);
- }
- }
-
- @Override
public void setCallIndicator(@NonNull IconState statusIcon, int subId) {
if (DEBUG) {
Log.d(TAG, "setCallIndicator: "
@@ -257,10 +199,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
return;
}
- // Visibility of the data type indicator changed
- boolean typeChanged = indicators.statusType != state.typeId
- && (indicators.statusType == 0 || state.typeId == 0);
-
state.visible = indicators.statusIcon.visible && !mHideMobile;
state.strengthId = indicators.statusIcon.icon;
state.typeId = indicators.statusType;
@@ -277,15 +215,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
}
// Always send a copy to maintain value type semantics
mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
-
- if (typeChanged) {
- WifiIconState wifiCopy = mWifiIconState.copy();
- updateShowWifiSignalSpacer(wifiCopy);
- if (!Objects.equals(wifiCopy, mWifiIconState)) {
- updateWifiIconWithState(wifiCopy);
- mWifiIconState = wifiCopy;
- }
- }
}
private CallIndicatorIconState getNoCallingState(int subId) {
@@ -308,15 +237,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
return null;
}
- private MobileIconState getFirstMobileState() {
- if (mMobileStates.size() > 0) {
- return mMobileStates.get(0);
- }
-
- return null;
- }
-
-
/**
* It is expected that a call to setSubs will be immediately followed by setMobileDataIndicators
* so we don't have to update the icon manager at this point, just remove the old ones
@@ -504,60 +424,6 @@ public class StatusBarSignalPolicy implements SignalCallback,
}
}
- public static class WifiIconState extends SignalIconState{
- public int resId;
- public boolean airplaneSpacerVisible;
- public boolean signalSpacerVisible;
- public boolean noDefaultNetwork;
- public boolean noValidatedNetwork;
- public boolean noNetworksAvailable;
-
- @Override
- public boolean equals(Object o) {
- // Skipping reference equality bc this should be more of a value type
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- if (!super.equals(o)) {
- return false;
- }
- WifiIconState that = (WifiIconState) o;
- return resId == that.resId
- && airplaneSpacerVisible == that.airplaneSpacerVisible
- && signalSpacerVisible == that.signalSpacerVisible
- && noDefaultNetwork == that.noDefaultNetwork
- && noValidatedNetwork == that.noValidatedNetwork
- && noNetworksAvailable == that.noNetworksAvailable;
- }
-
- public void copyTo(WifiIconState other) {
- super.copyTo(other);
- other.resId = resId;
- other.airplaneSpacerVisible = airplaneSpacerVisible;
- other.signalSpacerVisible = signalSpacerVisible;
- other.noDefaultNetwork = noDefaultNetwork;
- other.noValidatedNetwork = noValidatedNetwork;
- other.noNetworksAvailable = noNetworksAvailable;
- }
-
- public WifiIconState copy() {
- WifiIconState newState = new WifiIconState();
- copyTo(newState);
- return newState;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(),
- resId, airplaneSpacerVisible, signalSpacerVisible, noDefaultNetwork,
- noValidatedNetwork, noNetworksAvailable);
- }
-
- @Override public String toString() {
- return "WifiIconState(resId=" + resId + ", visible=" + visible + ")";
- }
- }
-
/**
* A little different. This one delegates to SignalDrawable instead of a specific resId
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
index 4a684d9f8e36..29829e46cda7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
@@ -45,18 +45,6 @@ constructor(
fun runNewMobileIconsBackend(): Boolean =
featureFlags.isEnabled(Flags.NEW_STATUS_BAR_MOBILE_ICONS_BACKEND) || useNewMobileIcons()
- /** True if we should display the wifi icon using the new status bar data pipeline. */
- fun useNewWifiIcon(): Boolean = featureFlags.isEnabled(Flags.NEW_STATUS_BAR_WIFI_ICON)
-
- /**
- * True if we should run the new wifi icon backend to get the logging.
- *
- * Does *not* affect whether we render the wifi icon using the new backend data. See
- * [useNewWifiIcon] for that.
- */
- fun runNewWifiIconBackend(): Boolean =
- featureFlags.isEnabled(Flags.NEW_STATUS_BAR_WIFI_ICON_BACKEND) || useNewWifiIcon()
-
/**
* Returns true if we should apply some coloring to the icons that were rendered with the new
* pipeline to help with debugging.
@@ -71,5 +59,5 @@ constructor(
* @return true if this icon is controlled by any of the status bar pipeline flags
*/
fun isIconControlledByFlags(slotName: String): Boolean =
- slotName == wifiSlot && useNewWifiIcon() || slotName == mobileSlot && useNewMobileIcons()
+ slotName == wifiSlot || (slotName == mobileSlot && useNewMobileIcons())
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
index 83738544ee84..a1b96dd327e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt
@@ -101,12 +101,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) :
this.binding = bindingCreator.invoke()
}
- /**
- * Creates a [StatusBarIconView] that is always in DOT mode and adds it to this view.
- *
- * Mostly duplicated from [com.android.systemui.statusbar.StatusBarWifiView] and
- * [com.android.systemui.statusbar.StatusBarMobileView].
- */
+ /** Creates a [StatusBarIconView] that is always in DOT mode and adds it to this view. */
private fun initDotView() {
// TODO(b/238425913): Could we just have this dot view be part of the layout with a dot
// drawable so we don't need to inflate it manually? Would that not work with animations?
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
index 174298ab6490..6d7182376fab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
@@ -68,12 +68,7 @@ constructor(
launch {
locationViewModel.wifiIcon.collect { wifiIcon ->
// Only notify the icon controller if we want to *render* the new icon.
- // Note that this flow may still run if
- // [statusBarPipelineFlags.runNewWifiIconBackend] is true because we may
- // want to get the logging data without rendering.
- if (
- wifiIcon is WifiIcon.Visible && statusBarPipelineFlags.useNewWifiIcon()
- ) {
+ if (wifiIcon is WifiIcon.Visible) {
iconController.setNewWifiIcon()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 9db267c2c929..d256ee163877 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -105,6 +105,7 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
`when`(keyguardPinView.findViewById<View>(R.id.key_enter)).thenReturn(enterButton)
// For posture tests:
`when`(keyguardPinView.buttons).thenReturn(arrayOf())
+ `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
pinViewController =
KeyguardPinViewController(
@@ -167,7 +168,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun startAppearAnimation_withAutoPinConfirmationFailedPasswordAttemptsLessThan5() {
`when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
- `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
`when`(lockPatternUtils.getCurrentFailedPasswordAttempts(anyInt())).thenReturn(3)
`when`(passwordTextView.text).thenReturn("")
@@ -182,7 +182,6 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Test
fun startAppearAnimation_withAutoPinConfirmationFailedPasswordAttemptsMoreThan5() {
`when`(featureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)).thenReturn(true)
- `when`(lockPatternUtils.getPinLength(anyInt())).thenReturn(6)
`when`(lockPatternUtils.isAutoPinConfirmEnabled(anyInt())).thenReturn(true)
`when`(lockPatternUtils.getCurrentFailedPasswordAttempts(anyInt())).thenReturn(6)
`when`(passwordTextView.text).thenReturn("")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
index 87811fb8fac0..40b572934f74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
@@ -33,9 +33,8 @@ import android.provider.Settings;
import androidx.test.filters.SmallTest;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarLocation;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -62,7 +61,6 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
private Handler mHandler;
@Mock
private ContentResolver mContentResolver;
- private FakeFeatureFlags mFeatureFlags;
@Mock
private BatteryController mBatteryController;
@@ -75,8 +73,8 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
when(mBatteryMeterView.getContext()).thenReturn(mContext);
when(mBatteryMeterView.getResources()).thenReturn(mContext.getResources());
- mFeatureFlags = new FakeFeatureFlags();
- mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.bool.flag_battery_shield_icon, false);
}
@Test
@@ -135,7 +133,8 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
@Test
public void shieldFlagDisabled_viewNotified() {
- mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, false);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.bool.flag_battery_shield_icon, false);
initController();
@@ -144,7 +143,8 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
@Test
public void shieldFlagEnabled_viewNotified() {
- mFeatureFlags.set(Flags.BATTERY_SHIELD_ICON, true);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.bool.flag_battery_shield_icon, true);
initController();
@@ -160,7 +160,6 @@ public class BatteryMeterViewControllerTest extends SysuiTestCase {
mTunerService,
mHandler,
mContentResolver,
- mFeatureFlags,
mBatteryController
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index 8aaa57ffe2cb..9157cd9e4f43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -16,7 +16,6 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
import static junit.framework.Assert.assertTrue;
@@ -41,13 +40,11 @@ import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
-import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
@@ -156,13 +153,9 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
assertTrue("Expected StatusBarIconView",
(manager.getViewAt(0) instanceof StatusBarIconView));
- holder = holderForType(TYPE_WIFI);
- manager.onIconAdded(1, "test_wifi", false, holder);
- assertTrue(manager.getViewAt(1) instanceof StatusBarWifiView);
-
holder = holderForType(TYPE_MOBILE);
- manager.onIconAdded(2, "test_mobile", false, holder);
- assertTrue(manager.getViewAt(2) instanceof StatusBarMobileView);
+ manager.onIconAdded(1, "test_mobile", false, holder);
+ assertTrue(manager.getViewAt(1) instanceof StatusBarMobileView);
}
private StatusBarIconHolder holderForType(int type) {
@@ -170,9 +163,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
case TYPE_MOBILE:
return StatusBarIconHolder.fromMobileIconState(mock(MobileIconState.class));
- case TYPE_WIFI:
- return StatusBarIconHolder.fromWifiIconState(mock(WifiIconState.class));
-
case TYPE_ICON:
default:
return StatusBarIconHolder.fromIcon(mock(StatusBarIcon.class));
@@ -214,13 +204,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
}
@Override
- protected StatusBarWifiView addWifiIcon(int index, String slot, WifiIconState state) {
- StatusBarWifiView mock = mock(StatusBarWifiView.class);
- mGroup.addView(mock, index);
- return mock;
- }
-
- @Override
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
StatusBarMobileView mock = mock(StatusBarMobileView.class);
mGroup.addView(mock, index);
@@ -254,13 +237,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
}
@Override
- protected StatusBarWifiView addWifiIcon(int index, String slot, WifiIconState state) {
- StatusBarWifiView mock = mock(StatusBarWifiView.class);
- mGroup.addView(mock, index);
- return mock;
- }
-
- @Override
protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) {
StatusBarMobileView mock = mock(StatusBarMobileView.class);
mGroup.addView(mock, index);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index c664c99cf2a7..56837e8cc7ef 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -21,7 +21,6 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.List;
@@ -62,10 +61,6 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
}
@Override
- public void setWifiIcon(String slot, WifiIconState state) {
- }
-
- @Override
public void setNewWifiIcon() {
}
diff --git a/services/Android.bp b/services/Android.bp
index 453f57234145..b0a0e5e44a8c 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -159,7 +159,6 @@ java_library {
"services.coverage",
"services.credentials",
"services.devicepolicy",
- "services.flags",
"services.midi",
"services.musicsearch",
"services.net",
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index ca15dd79adbc..c6d6122aeed6 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -40,6 +40,7 @@ import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameManagerService;
import android.app.IGameModeListener;
+import android.app.IGameStateListener;
import android.app.StatsManager;
import android.app.UidObserver;
import android.content.BroadcastReceiver;
@@ -148,6 +149,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
private final Object mLock = new Object();
private final Object mDeviceConfigLock = new Object();
private final Object mGameModeListenerLock = new Object();
+ private final Object mGameStateListenerLock = new Object();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
final Handler mHandler;
private final PackageManager mPackageManager;
@@ -164,6 +166,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
// listener to caller uid map
@GuardedBy("mGameModeListenerLock")
private final ArrayMap<IGameModeListener, Integer> mGameModeListeners = new ArrayMap<>();
+ @GuardedBy("mGameStateListenerLock")
+ private final ArrayMap<IGameStateListener, Integer> mGameStateListeners = new ArrayMap<>();
@Nullable
private final GameServiceController mGameServiceController;
private final Object mUidObserverLock = new Object();
@@ -352,6 +356,16 @@ public final class GameManagerService extends IGameManagerService.Stub {
loadingBoostDuration);
}
}
+ synchronized (mGameStateListenerLock) {
+ for (IGameStateListener listener : mGameStateListeners.keySet()) {
+ try {
+ listener.onGameStateChanged(packageName, gameState, userId);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Cannot notify game state change for listener added by "
+ + mGameStateListeners.get(listener));
+ }
+ }
+ }
break;
}
case CANCEL_GAME_LOADING_MODE: {
@@ -1474,6 +1488,43 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
/**
+ * Adds a game state listener.
+ */
+ @Override
+ public void addGameStateListener(@NonNull IGameStateListener listener) {
+ try {
+ final IBinder listenerBinder = listener.asBinder();
+ listenerBinder.linkToDeath(new DeathRecipient() {
+ @Override public void binderDied() {
+ removeGameStateListenerUnchecked(listener);
+ listenerBinder.unlinkToDeath(this, 0 /*flags*/);
+ }
+ }, 0 /*flags*/);
+ synchronized (mGameStateListenerLock) {
+ mGameStateListeners.put(listener, Binder.getCallingUid());
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG,
+ "Failed to link death recipient for IGameStateListener from caller "
+ + Binder.getCallingUid() + ", abandoned its listener registration", ex);
+ }
+ }
+
+ /**
+ * Removes a game state listener.
+ */
+ @Override
+ public void removeGameStateListener(@NonNull IGameStateListener listener) {
+ removeGameStateListenerUnchecked(listener);
+ }
+
+ private void removeGameStateListenerUnchecked(IGameStateListener listener) {
+ synchronized (mGameStateListenerLock) {
+ mGameStateListeners.remove(listener);
+ }
+ }
+
+ /**
* Notified when boot is completed.
*/
@VisibleForTesting
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
index f1698dd0f025..a1b67e105dd4 100644
--- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -37,7 +37,6 @@ import android.os.ResultReceiver;
import android.util.EventLog;
import android.util.Slog;
import android.view.inputmethod.ImeTracker;
-import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.GuardedBy;
@@ -76,8 +75,7 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
@GuardedBy("ImfLock.class")
@Override
public void performShowIme(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
- @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
final IInputMethodInvoker curMethod = mService.getCurMethodLocked();
if (curMethod != null) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
index b12a816738da..c53f1a52306d 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
@@ -30,7 +30,6 @@ import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ImeTracker;
import android.view.inputmethod.InputBinding;
-import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSubtype;
import android.window.ImeOnBackInvokedDispatcher;
@@ -199,8 +198,8 @@ final class IInputMethodInvoker {
// TODO(b/192412909): Convert this back to void method
@AnyThread
- boolean showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
- @InputMethod.ShowFlags int flags, ResultReceiver resultReceiver) {
+ boolean showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken, int flags,
+ ResultReceiver resultReceiver) {
try {
mTarget.showSoftInput(showInputToken, statsToken, flags, resultReceiver);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
index 29fa36982351..27f6a89a73b3 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
@@ -21,7 +21,6 @@ import android.annotation.Nullable;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.view.inputmethod.ImeTracker;
-import android.view.inputmethod.InputMethod;
import com.android.internal.inputmethod.SoftInputShowHideReason;
@@ -35,13 +34,13 @@ interface ImeVisibilityApplier {
*
* @param showInputToken A token that represents the requester to show IME.
* @param statsToken A token that tracks the progress of an IME request.
+ * @param showFlags Provides additional operating flags to show IME.
* @param resultReceiver If non-null, this will be called back to the caller when
* it has processed request to tell what it has done.
* @param reason The reason for requesting to show IME.
*/
default void performShowIme(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
- @InputMethod.ShowFlags int showFlags, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {}
+ int showFlags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {}
/**
* Performs hiding IME to the given window
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 9ad4628596fc..f012d917b05e 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -221,21 +221,17 @@ public final class ImeVisibilityStateComputer {
/**
* Called when {@link InputMethodManagerService} is processing the show IME request.
- *
- * @param statsToken The token for tracking this show request.
- * @return {@code true} when the show request can proceed.
+ * @param statsToken The token for tracking this show request
+ * @param showFlags The additional operation flags to indicate whether this show request mode is
+ * implicit or explicit.
+ * @return {@code true} when the computer has proceed this show request operation.
*/
- boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken,
- @InputMethodManager.ShowFlags int showFlags) {
+ boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken, int showFlags) {
if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
return false;
}
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
- // We only "set" the state corresponding to the flags, as this will be reset
- // in clearImeShowFlags during a hide request.
- // Thus, we keep the strongest values set (e.g. an implicit show right after
- // an explicit show will still be considered explicit, likewise for forced).
if ((showFlags & InputMethodManager.SHOW_FORCED) != 0) {
mRequestedShowExplicitly = true;
mShowForced = true;
@@ -247,12 +243,12 @@ public final class ImeVisibilityStateComputer {
/**
* Called when {@link InputMethodManagerService} is processing the hide IME request.
- *
- * @param statsToken The token for tracking this hide request.
- * @return {@code true} when the hide request can proceed.
+ * @param statsToken The token for tracking this hide request
+ * @param hideFlags The additional operation flags to indicate whether this hide request mode is
+ * implicit or explicit.
+ * @return {@code true} when the computer has proceed this hide request operations.
*/
- boolean canHideIme(@NonNull ImeTracker.Token statsToken,
- @InputMethodManager.HideFlags int hideFlags) {
+ boolean canHideIme(@NonNull ImeTracker.Token statsToken, int hideFlags) {
if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mRequestedShowExplicitly || mShowForced)) {
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
@@ -268,31 +264,13 @@ public final class ImeVisibilityStateComputer {
return true;
}
- /**
- * Returns the show flags for IME. This translates from {@link InputMethodManager.ShowFlags}
- * to {@link InputMethod.ShowFlags}.
- */
- @InputMethod.ShowFlags
- int getShowFlagsForInputMethodServiceOnly() {
+ int getImeShowFlags() {
int flags = 0;
if (mShowForced) {
flags |= InputMethod.SHOW_FORCED | InputMethod.SHOW_EXPLICIT;
} else if (mRequestedShowExplicitly) {
flags |= InputMethod.SHOW_EXPLICIT;
- }
- return flags;
- }
-
- /**
- * Returns the show flags for IMM. This translates from {@link InputMethod.ShowFlags}
- * to {@link InputMethodManager.ShowFlags}.
- */
- @InputMethodManager.ShowFlags
- int getShowFlags() {
- int flags = 0;
- if (mShowForced) {
- flags |= InputMethodManager.SHOW_FORCED;
- } else if (!mRequestedShowExplicitly) {
+ } else {
flags |= InputMethodManager.SHOW_IMPLICIT;
}
return flags;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0bf282059066..02ee96a04b1f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2462,7 +2462,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final ImeTracker.Token statsToken = mCurStatsToken;
mCurStatsToken = null;
showCurrentInputLocked(mCurFocusedWindow, statsToken,
- mVisibilityStateComputer.getShowFlags(),
+ mVisibilityStateComputer.getImeShowFlags(),
null /* resultReceiver */, SoftInputShowHideReason.ATTACH_NEW_INPUT);
}
@@ -3398,9 +3398,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
- @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
- int lastClickTooType, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ @Nullable ImeTracker.Token statsToken, int flags, int lastClickTooType,
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
int uid = Binder.getCallingUid();
ImeTracing.getInstance().triggerManagerServiceDump(
@@ -3573,17 +3572,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class")
boolean showCurrentInputLocked(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
- @InputMethodManager.ShowFlags int flags, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
return showCurrentInputLocked(windowToken, statsToken, flags,
MotionEvent.TOOL_TYPE_UNKNOWN, resultReceiver, reason);
}
@GuardedBy("ImfLock.class")
private boolean showCurrentInputLocked(IBinder windowToken,
- @Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
- int lastClickToolType, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ @Nullable ImeTracker.Token statsToken, int flags, int lastClickToolType,
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
// Create statsToken is none exists.
if (statsToken == null) {
statsToken = createStatsTokenForFocusedClient(true /* show */,
@@ -3614,8 +3611,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
curMethod.updateEditorToolType(lastClickToolType);
}
mVisibilityApplier.performShowIme(windowToken, statsToken,
- mVisibilityStateComputer.getShowFlagsForInputMethodServiceOnly(),
- resultReceiver, reason);
+ mVisibilityStateComputer.getImeShowFlags(), resultReceiver, reason);
mVisibilityStateComputer.setInputShown(true);
return true;
} else {
@@ -3627,8 +3623,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
- @Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
- ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+ @Nullable ImeTracker.Token statsToken, int flags, ResultReceiver resultReceiver,
+ @SoftInputShowHideReason int reason) {
int uid = Binder.getCallingUid();
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#hideSoftInput");
@@ -3658,8 +3654,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class")
boolean hideCurrentInputLocked(IBinder windowToken, @Nullable ImeTracker.Token statsToken,
- @InputMethodManager.HideFlags int flags, ResultReceiver resultReceiver,
- @SoftInputShowHideReason int reason) {
+ int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
// Create statsToken is none exists.
if (statsToken == null) {
statsToken = createStatsTokenForFocusedClient(false /* show */,
@@ -4846,7 +4841,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@BinderThread
- private void hideMySoftInput(@NonNull IBinder token, @InputMethodManager.HideFlags int flags,
+ private void hideMySoftInput(@NonNull IBinder token, int flags,
@SoftInputShowHideReason int reason) {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
@@ -4868,7 +4863,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@BinderThread
- private void showMySoftInput(@NonNull IBinder token, @InputMethodManager.ShowFlags int flags) {
+ private void showMySoftInput(@NonNull IBinder token, int flags) {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
synchronized (ImfLock.class) {
@@ -6827,8 +6822,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
@Override
- public void hideMySoftInput(@InputMethodManager.HideFlags int flags,
- @SoftInputShowHideReason int reason, AndroidFuture future /* T=Void */) {
+ public void hideMySoftInput(int flags, @SoftInputShowHideReason int reason,
+ AndroidFuture future /* T=Void */) {
@SuppressWarnings("unchecked")
final AndroidFuture<Void> typedFuture = future;
try {
@@ -6841,8 +6836,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
@Override
- public void showMySoftInput(@InputMethodManager.ShowFlags int flags,
- AndroidFuture future /* T=Void */) {
+ public void showMySoftInput(int flags, AndroidFuture future /* T=Void */) {
@SuppressWarnings("unchecked")
final AndroidFuture<Void> typedFuture = future;
try {
diff --git a/services/flags/Android.bp b/services/flags/Android.bp
deleted file mode 100644
index 29d2b9cfbb98..000000000000
--- a/services/flags/Android.bp
+++ /dev/null
@@ -1,18 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library_static {
- name: "services.flags",
- defaults: ["platform_service_defaults"],
- srcs: [
- "java/**/*.java",
- ":feature_flags_aidl",
- ],
- libs: ["services.core"],
-}
diff --git a/services/flags/OWNERS b/services/flags/OWNERS
deleted file mode 100644
index 3925b5c13c2d..000000000000
--- a/services/flags/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 1306523
-
-mankoff@google.com
-
-pixel@google.com
-dsandler@android.com
diff --git a/services/flags/java/com/android/server/flags/DynamicFlagBinderDelegate.java b/services/flags/java/com/android/server/flags/DynamicFlagBinderDelegate.java
deleted file mode 100644
index 0db328792cf3..000000000000
--- a/services/flags/java/com/android/server/flags/DynamicFlagBinderDelegate.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import android.annotation.NonNull;
-import android.flags.IFeatureFlagsCallback;
-import android.flags.SyncableFlag;
-import android.os.Build;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.provider.DeviceConfig;
-import android.util.Slog;
-
-import com.android.internal.os.BackgroundThread;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Function;
-
-/**
- * Handles DynamicFlags for {@link FeatureFlagsBinder}.
- *
- * Dynamic flags are simultaneously simpler and more complicated than process stable flags. We can
- * return whatever value is last known for a flag is, without too much worry about the flags
- * changing (they are dynamic after all). However, we have to alert all the relevant clients
- * about those flag changes, and need to be able to restore to a default value if the flag gets
- * reset/erased during runtime.
- */
-class DynamicFlagBinderDelegate {
-
- private final FlagOverrideStore mFlagStore;
- private final FlagCache<DynamicFlagData> mDynamicFlags = new FlagCache<>();
- private final Map<Integer, Set<IFeatureFlagsCallback>> mCallbacks = new HashMap<>();
- private static final Function<Integer, Set<IFeatureFlagsCallback>> NEW_CALLBACK_SET =
- k -> new HashSet<>();
-
- private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener =
- new DeviceConfig.OnPropertiesChangedListener() {
- @Override
- public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
- String ns = properties.getNamespace();
- for (String name : properties.getKeyset()) {
- // Don't alert for flags we don't care about.
- // Don't alert for flags that have been overridden locally.
- if (!mDynamicFlags.contains(ns, name) || mFlagStore.contains(ns, name)) {
- continue;
- }
- mFlagChangeCallback.onFlagChanged(
- ns, name, properties.getString(name, null));
- }
- }
- };
-
- private final FlagOverrideStore.FlagChangeCallback mFlagChangeCallback =
- (namespace, name, value) -> {
- // Don't bother with callbacks for non-dynamic flags.
- if (!mDynamicFlags.contains(namespace, name)) {
- return;
- }
-
- // Don't bother with callbacks if nothing changed.
- // Handling erasure (null) is special, as we may be restoring back to a value
- // we were already at.
- DynamicFlagData data = mDynamicFlags.getOrNull(namespace, name);
- if (data == null) {
- return; // shouldn't happen, but better safe than sorry.
- }
- if (value == null) {
- if (data.getValue().equals(data.getDefaultValue())) {
- return;
- }
- value = data.getDefaultValue();
- } else if (data.getValue().equals(value)) {
- return;
- }
- data.setValue(value);
-
- final Set<IFeatureFlagsCallback> cbCopy;
- synchronized (mCallbacks) {
- cbCopy = new HashSet<>();
-
- for (Integer pid : mCallbacks.keySet()) {
- if (data.containsPid(pid)) {
- cbCopy.addAll(mCallbacks.get(pid));
- }
- }
- }
- SyncableFlag sFlag = new SyncableFlag(namespace, name, value, true);
- cbCopy.forEach(cb -> {
- try {
- cb.onFlagChange(sFlag);
- } catch (RemoteException e) {
- Slog.w(
- FeatureFlagsService.TAG,
- "Failed to communicate flag change to client.");
- }
- });
- };
-
- DynamicFlagBinderDelegate(FlagOverrideStore flagStore) {
- mFlagStore = flagStore;
- mFlagStore.setChangeCallback(mFlagChangeCallback);
- }
-
- SyncableFlag syncDynamicFlag(int pid, SyncableFlag sf) {
- if (!sf.isDynamic()) {
- return sf;
- }
-
- String ns = sf.getNamespace();
- String name = sf.getName();
-
- // Dynamic flags don't need any special threading or synchronization considerations.
- // We simply give them whatever the current value is.
- // However, we do need to keep track of dynamic flags, so that we can alert
- // about changes coming in from adb, DeviceConfig, or other sources.
- // And also so that we can keep flags relatively consistent across processes.
-
- DynamicFlagData data = mDynamicFlags.getOrNull(ns, name);
- String value = getFlagValue(ns, name, sf.getValue());
- // DeviceConfig listeners are per-namespace.
- if (!mDynamicFlags.containsNamespace(ns)) {
- DeviceConfig.addOnPropertiesChangedListener(
- ns, BackgroundThread.getExecutor(), mDeviceConfigListener);
- }
- data.addClientPid(pid);
- data.setValue(value);
- // Store the default value so that if an override gets erased, we can restore
- // to something.
- data.setDefaultValue(sf.getValue());
-
- return new SyncableFlag(sf.getNamespace(), sf.getName(), value, true);
- }
-
-
- void registerCallback(int pid, IFeatureFlagsCallback callback) {
- // Always add callback so that we don't end up with a possible race/leak.
- // We remove the callback directly if we fail to call #linkToDeath.
- // If we tried to add the callback after we linked, then we could end up in a
- // scenario where we link, then the binder dies, firing our BinderGriever which tries
- // to remove the callback (which has not yet been added), then finally we add the
- // callback, creating a leak.
- Set<IFeatureFlagsCallback> callbacks;
- synchronized (mCallbacks) {
- callbacks = mCallbacks.computeIfAbsent(pid, NEW_CALLBACK_SET);
- callbacks.add(callback);
- }
- try {
- callback.asBinder().linkToDeath(new BinderGriever(pid), 0);
- } catch (RemoteException e) {
- Slog.e(
- FeatureFlagsService.TAG,
- "Failed to link to binder death. Callback not registered.");
- synchronized (mCallbacks) {
- callbacks.remove(callback);
- }
- }
- }
-
- void unregisterCallback(int pid, IFeatureFlagsCallback callback) {
- // No need to unlink, since the BinderGriever will essentially be a no-op.
- // We would have to track our BinderGriever's in a map otherwise.
- synchronized (mCallbacks) {
- Set<IFeatureFlagsCallback> callbacks =
- mCallbacks.computeIfAbsent(pid, NEW_CALLBACK_SET);
- callbacks.remove(callback);
- }
- }
-
- String getFlagValue(String namespace, String name, String defaultValue) {
- // If we already have a value cached, just use that.
- String value = null;
- DynamicFlagData data = mDynamicFlags.getOrNull(namespace, name);
- if (data != null) {
- value = data.getValue();
- } else {
- // Put the value in the cache for future reference.
- data = new DynamicFlagData(namespace, name);
- mDynamicFlags.setIfChanged(namespace, name, data);
- }
- // If we're not in a release build, flags can be overridden locally on device.
- if (!Build.IS_USER && value == null) {
- value = mFlagStore.get(namespace, name);
- }
- // If we still don't have a value, maybe DeviceConfig does?
- // Fallback to sf.getValue() here as well.
- if (value == null) {
- value = DeviceConfig.getString(namespace, name, defaultValue);
- }
-
- return value;
- }
-
- private static class DynamicFlagData {
- private final String mNamespace;
- private final String mName;
- private final Set<Integer> mPids = new HashSet<>();
- private String mValue;
- private String mDefaultValue;
-
- private DynamicFlagData(String namespace, String name) {
- mNamespace = namespace;
- mName = name;
- }
-
- String getValue() {
- return mValue;
- }
-
- void setValue(String value) {
- mValue = value;
- }
-
- String getDefaultValue() {
- return mDefaultValue;
- }
-
- void setDefaultValue(String value) {
- mDefaultValue = value;
- }
-
- void addClientPid(int pid) {
- mPids.add(pid);
- }
-
- boolean containsPid(int pid) {
- return mPids.contains(pid);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == null || !(other instanceof DynamicFlagData)) {
- return false;
- }
-
- DynamicFlagData o = (DynamicFlagData) other;
-
- return mName.equals(o.mName) && mNamespace.equals(o.mNamespace)
- && mValue.equals(o.mValue) && mDefaultValue.equals(o.mDefaultValue);
- }
-
- @Override
- public int hashCode() {
- return mName.hashCode() + mNamespace.hashCode()
- + mValue.hashCode() + mDefaultValue.hashCode();
- }
- }
-
-
- private class BinderGriever implements IBinder.DeathRecipient {
- private final int mPid;
-
- private BinderGriever(int pid) {
- mPid = pid;
- }
-
- @Override
- public void binderDied() {
- synchronized (mCallbacks) {
- mCallbacks.remove(mPid);
- }
- }
- }
-}
diff --git a/services/flags/java/com/android/server/flags/FeatureFlagsBinder.java b/services/flags/java/com/android/server/flags/FeatureFlagsBinder.java
deleted file mode 100644
index 1fa85325aea6..000000000000
--- a/services/flags/java/com/android/server/flags/FeatureFlagsBinder.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.flags.IFeatureFlags;
-import android.flags.IFeatureFlagsCallback;
-import android.flags.SyncableFlag;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-
-import com.android.internal.flags.CoreFlags;
-import com.android.server.flags.FeatureFlagsService.PermissionsChecker;
-
-import java.io.FileOutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-class FeatureFlagsBinder extends IFeatureFlags.Stub {
- private final FlagOverrideStore mFlagStore;
- private final FlagsShellCommand mShellCommand;
- private final FlagCache<String> mFlagCache = new FlagCache<>();
- private final DynamicFlagBinderDelegate mDynamicFlagDelegate;
- private final PermissionsChecker mPermissionsChecker;
-
- FeatureFlagsBinder(
- FlagOverrideStore flagStore,
- FlagsShellCommand shellCommand,
- PermissionsChecker permissionsChecker) {
- mFlagStore = flagStore;
- mShellCommand = shellCommand;
- mDynamicFlagDelegate = new DynamicFlagBinderDelegate(flagStore);
- mPermissionsChecker = permissionsChecker;
- }
-
- @Override
- public void registerCallback(IFeatureFlagsCallback callback) {
- mDynamicFlagDelegate.registerCallback(getCallingPid(), callback);
- }
-
- @Override
- public void unregisterCallback(IFeatureFlagsCallback callback) {
- mDynamicFlagDelegate.unregisterCallback(getCallingPid(), callback);
- }
-
- // Note: The internals of this method should be kept in sync with queryFlags
- // as they both should return identical results. The difference is that this method
- // caches any values it receives and/or reads, whereas queryFlags does not.
-
- @Override
- public List<SyncableFlag> syncFlags(List<SyncableFlag> incomingFlags) {
- int pid = getCallingPid();
- List<SyncableFlag> outputFlags = new ArrayList<>();
-
- boolean hasFullSyncPrivileges = false;
- SecurityException permissionFailureException = null;
- try {
- assertSyncPermission();
- hasFullSyncPrivileges = true;
- } catch (SecurityException e) {
- permissionFailureException = e;
- }
-
- for (SyncableFlag sf : incomingFlags) {
- if (!hasFullSyncPrivileges && !CoreFlags.isCoreFlag(sf)) {
- throw permissionFailureException;
- }
-
- String ns = sf.getNamespace();
- String name = sf.getName();
- SyncableFlag outFlag;
- if (sf.isDynamic()) {
- outFlag = mDynamicFlagDelegate.syncDynamicFlag(pid, sf);
- } else {
- synchronized (mFlagCache) {
- String value = mFlagCache.getOrNull(ns, name);
- if (value == null) {
- String overrideValue = Build.IS_USER ? null : mFlagStore.get(ns, name);
- value = overrideValue != null ? overrideValue : sf.getValue();
- mFlagCache.setIfChanged(ns, name, value);
- }
- outFlag = new SyncableFlag(sf.getNamespace(), sf.getName(), value, false);
- }
- }
- outputFlags.add(outFlag);
- }
- return outputFlags;
- }
-
- @Override
- public void overrideFlag(SyncableFlag flag) {
- assertWritePermission();
- mFlagStore.set(flag.getNamespace(), flag.getName(), flag.getValue());
- }
-
- @Override
- public void resetFlag(SyncableFlag flag) {
- assertWritePermission();
- mFlagStore.erase(flag.getNamespace(), flag.getName());
- }
-
- @Override
- public List<SyncableFlag> queryFlags(List<SyncableFlag> incomingFlags) {
- assertSyncPermission();
- List<SyncableFlag> outputFlags = new ArrayList<>();
- for (SyncableFlag sf : incomingFlags) {
- String ns = sf.getNamespace();
- String name = sf.getName();
- String value;
- String storeValue = mFlagStore.get(ns, name);
- boolean overridden = storeValue != null;
-
- if (sf.isDynamic()) {
- value = mDynamicFlagDelegate.getFlagValue(ns, name, sf.getValue());
- } else {
- value = mFlagCache.getOrNull(ns, name);
- if (value == null) {
- value = Build.IS_USER ? null : storeValue;
- if (value == null) {
- value = sf.getValue();
- }
- }
- }
- outputFlags.add(new SyncableFlag(
- sf.getNamespace(), sf.getName(), value, sf.isDynamic(), overridden));
- }
-
- return outputFlags;
- }
-
- private void assertSyncPermission() {
- mPermissionsChecker.assertSyncPermission();
- clearCallingIdentity();
- }
-
- private void assertWritePermission() {
- mPermissionsChecker.assertWritePermission();
- clearCallingIdentity();
- }
-
-
- @SystemApi
- public int handleShellCommand(
- @NonNull ParcelFileDescriptor in,
- @NonNull ParcelFileDescriptor out,
- @NonNull ParcelFileDescriptor err,
- @NonNull String[] args) {
- FileOutputStream fout = new FileOutputStream(out.getFileDescriptor());
- FileOutputStream ferr = new FileOutputStream(err.getFileDescriptor());
-
- return mShellCommand.process(args, fout, ferr);
- }
-}
diff --git a/services/flags/java/com/android/server/flags/FeatureFlagsService.java b/services/flags/java/com/android/server/flags/FeatureFlagsService.java
deleted file mode 100644
index 93b9e9e0dc8c..000000000000
--- a/services/flags/java/com/android/server/flags/FeatureFlagsService.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import static android.Manifest.permission.SYNC_FLAGS;
-import static android.Manifest.permission.WRITE_FLAGS;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.flags.FeatureFlags;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.SystemService;
-
-/**
- * A service that manages syncing {@link android.flags.FeatureFlags} across processes.
- *
- * This service holds flags stable for at least the lifetime of a process, meaning that if
- * a process comes online with a flag set to true, any other process that connects here and
- * tries to read the same flag will also receive the flag as true. The flag will remain stable
- * until either all of the interested processes have died, or the device restarts.
- *
- * TODO(279054964): Add to dumpsys
- * @hide
- */
-public class FeatureFlagsService extends SystemService {
-
- static final String TAG = "FeatureFlagsService";
- private final FlagOverrideStore mFlagStore;
- private final FlagsShellCommand mShellCommand;
-
- /**
- * Initializes the system service.
- *
- * @param context The system server context.
- */
- public FeatureFlagsService(Context context) {
- super(context);
- mFlagStore = new FlagOverrideStore(
- new GlobalSettingsProxy(context.getContentResolver()));
- mShellCommand = new FlagsShellCommand(mFlagStore);
- }
-
- @Override
- public void onStart() {
- Slog.d(TAG, "Started Feature Flag Service");
- FeatureFlagsBinder service = new FeatureFlagsBinder(
- mFlagStore, mShellCommand, new PermissionsChecker(getContext()));
- publishBinderService(
- Context.FEATURE_FLAGS_SERVICE, service);
- publishLocalService(FeatureFlags.class, new FeatureFlags(service));
- }
-
- @Override
- public void onBootPhase(int phase) {
- super.onBootPhase(phase);
-
- if (phase == PHASE_SYSTEM_SERVICES_READY) {
- // Immediately sync our core flags so that they get locked in. We don't want third-party
- // apps to override them, and syncing immediately is the easiest way to prevent that.
- FeatureFlags.getInstance().sync();
- }
- }
-
- /**
- * Delegate for checking flag permissions.
- */
- @VisibleForTesting
- public static class PermissionsChecker {
- private final Context mContext;
-
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public PermissionsChecker(Context context) {
- mContext = context;
- }
-
- /**
- * Ensures that the caller has {@link SYNC_FLAGS} permission.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void assertSyncPermission() {
- if (mContext.checkCallingOrSelfPermission(SYNC_FLAGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "Non-core flag queried. Requires SYNC_FLAGS permission!");
- }
- }
-
- /**
- * Ensures that the caller has {@link WRITE_FLAGS} permission.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void assertWritePermission() {
- if (mContext.checkCallingPermission(WRITE_FLAGS) != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires WRITE_FLAGS permission!");
- }
- }
- }
-}
diff --git a/services/flags/java/com/android/server/flags/FlagCache.java b/services/flags/java/com/android/server/flags/FlagCache.java
deleted file mode 100644
index cee1578a5dde..000000000000
--- a/services/flags/java/com/android/server/flags/FlagCache.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Function;
-
-/**
- * Threadsafe cache of values that stores the supplied default on cache miss.
- *
- * @param <V> The type of value to store.
- */
-public class FlagCache<V> {
- private final Function<String, HashMap<String, V>> mNewHashMap = k -> new HashMap<>();
-
- // Cache is organized first by namespace, then by name. All values are stored as strings.
- final Map<String, Map<String, V>> mCache = new HashMap<>();
-
- FlagCache() {
- }
-
- /**
- * Returns true if the namespace exists in the cache already.
- */
- boolean containsNamespace(String namespace) {
- synchronized (mCache) {
- return mCache.containsKey(namespace);
- }
- }
-
- /**
- * Returns true if the value is stored in the cache.
- */
- boolean contains(String namespace, String name) {
- synchronized (mCache) {
- Map<String, V> nsCache = mCache.get(namespace);
- return nsCache != null && nsCache.containsKey(name);
- }
- }
-
- /**
- * Sets the value if it is different from what is currently stored.
- *
- * If the value is not set, or the current value is null, it will store the value and
- * return true.
- *
- * @return True if the value was set. False if the value is the same.
- */
- boolean setIfChanged(String namespace, String name, V value) {
- synchronized (mCache) {
- Map<String, V> nsCache = mCache.computeIfAbsent(namespace, mNewHashMap);
- V curValue = nsCache.get(name);
- if (curValue == null || !curValue.equals(value)) {
- nsCache.put(name, value);
- return true;
- }
- return false;
- }
- }
-
- /**
- * Gets the current value from the cache, setting it if it is currently absent.
- *
- * @return The value that is now in the cache after the call to the method.
- */
- V getOrSet(String namespace, String name, V defaultValue) {
- synchronized (mCache) {
- Map<String, V> nsCache = mCache.computeIfAbsent(namespace, mNewHashMap);
- V value = nsCache.putIfAbsent(name, defaultValue);
- return value == null ? defaultValue : value;
- }
- }
-
- /**
- * Gets the current value from the cache, returning null if not present.
- *
- * @return The value that is now in the cache if there is one.
- */
- V getOrNull(String namespace, String name) {
- synchronized (mCache) {
- Map<String, V> nsCache = mCache.get(namespace);
- if (nsCache == null) {
- return null;
- }
- return nsCache.get(name);
- }
- }
-}
diff --git a/services/flags/java/com/android/server/flags/FlagOverrideStore.java b/services/flags/java/com/android/server/flags/FlagOverrideStore.java
deleted file mode 100644
index b1ddc7e67f68..000000000000
--- a/services/flags/java/com/android/server/flags/FlagOverrideStore.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import android.database.Cursor;
-import android.provider.Settings;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Persistent storage for the {@link FeatureFlagsService}.
- *
- * The implementation stores data in Settings.<store> (generally {@link Settings.Global}
- * is expected).
- */
-@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class FlagOverrideStore {
- private static final String KEYNAME_PREFIX = "flag|";
- private static final String NAMESPACE_NAME_SEPARATOR = ".";
-
- private final SettingsProxy mSettingsProxy;
-
- private FlagChangeCallback mCallback;
-
- FlagOverrideStore(SettingsProxy settingsProxy) {
- mSettingsProxy = settingsProxy;
- }
-
- void setChangeCallback(FlagChangeCallback callback) {
- mCallback = callback;
- }
-
- /** Returns true if a non-null value is in the store. */
- boolean contains(String namespace, String name) {
- return get(namespace, name) != null;
- }
-
- /** Put a value in the store. */
- @VisibleForTesting
- public void set(String namespace, String name, String value) {
- mSettingsProxy.putString(getPropName(namespace, name), value);
- mCallback.onFlagChanged(namespace, name, value);
- }
-
- /** Read a value out of the store. */
- @VisibleForTesting
- public String get(String namespace, String name) {
- return mSettingsProxy.getString(getPropName(namespace, name));
- }
-
- /** Erase a value from the store. */
- @VisibleForTesting
- public void erase(String namespace, String name) {
- set(namespace, name, null);
- }
-
- Map<String, Map<String, String>> getFlags() {
- return getFlagsForNamespace(null);
- }
-
- Map<String, Map<String, String>> getFlagsForNamespace(String namespace) {
- Cursor c = mSettingsProxy.getContentResolver().query(
- Settings.Global.CONTENT_URI,
- new String[]{Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE},
- null, // Doesn't support a "LIKE" query
- null,
- null
- );
-
- if (c == null) {
- return Map.of();
- }
- int keynamePrefixLength = KEYNAME_PREFIX.length();
- Map<String, Map<String, String>> results = new HashMap<>();
- while (c.moveToNext()) {
- String key = c.getString(0);
- if (!key.startsWith(KEYNAME_PREFIX)
- || key.indexOf(NAMESPACE_NAME_SEPARATOR, keynamePrefixLength) < 0) {
- continue;
- }
- String value = c.getString(1);
- if (value == null || value.isEmpty()) {
- continue;
- }
- String ns = key.substring(keynamePrefixLength, key.indexOf(NAMESPACE_NAME_SEPARATOR));
- if (namespace != null && !namespace.equals(ns)) {
- continue;
- }
- String name = key.substring(key.indexOf(NAMESPACE_NAME_SEPARATOR) + 1);
- results.putIfAbsent(ns, new HashMap<>());
- results.get(ns).put(name, value);
- }
- c.close();
- return results;
- }
-
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- static String getPropName(String namespace, String name) {
- return KEYNAME_PREFIX + namespace + NAMESPACE_NAME_SEPARATOR + name;
- }
-
- interface FlagChangeCallback {
- void onFlagChanged(String namespace, String name, String value);
- }
-}
diff --git a/services/flags/java/com/android/server/flags/FlagsShellCommand.java b/services/flags/java/com/android/server/flags/FlagsShellCommand.java
deleted file mode 100644
index b7896ee18714..000000000000
--- a/services/flags/java/com/android/server/flags/FlagsShellCommand.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FastPrintWriter;
-
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Process command line input for the flags service.
- */
-@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class FlagsShellCommand {
- private final FlagOverrideStore mFlagStore;
-
- FlagsShellCommand(FlagOverrideStore flagStore) {
- mFlagStore = flagStore;
- }
-
- /**
- * Interpret the command supplied in the constructor.
- *
- * @return Zero on success or non-zero on error.
- */
- public int process(
- String[] args,
- OutputStream out,
- OutputStream err) {
- PrintWriter outPw = new FastPrintWriter(out);
- PrintWriter errPw = new FastPrintWriter(err);
-
- if (args.length == 0) {
- return printHelp(outPw);
- }
- switch (args[0].toLowerCase(Locale.ROOT)) {
- case "help":
- return printHelp(outPw);
- case "list":
- return listCmd(args, outPw, errPw);
- case "set":
- return setCmd(args, outPw, errPw);
- case "get":
- return getCmd(args, outPw, errPw);
- case "erase":
- return eraseCmd(args, outPw, errPw);
- default:
- return unknownCmd(outPw);
- }
- }
-
- private int printHelp(PrintWriter outPw) {
- outPw.println("Feature Flags command, allowing listing, setting, getting, and erasing of");
- outPw.println("local flag overrides on a device.");
- outPw.println();
- outPw.println("Commands:");
- outPw.println(" list [namespace]");
- outPw.println(" List all flag overrides. Namespace is optional.");
- outPw.println();
- outPw.println(" get <namespace> <name>");
- outPw.println(" Return the string value of a specific flag, or <unset>");
- outPw.println();
- outPw.println(" set <namespace> <name> <value>");
- outPw.println(" Set a specific flag");
- outPw.println();
- outPw.println(" erase <namespace> <name>");
- outPw.println(" Unset a specific flag");
- outPw.flush();
- return 0;
- }
-
- private int listCmd(String[] args, PrintWriter outPw, PrintWriter errPw) {
- if (!validateNumArguments(args, 0, 1, args[0], errPw)) {
- errPw.println("Expected `" + args[0] + " [namespace]`");
- errPw.flush();
- return -1;
- }
- Map<String, Map<String, String>> overrides;
- if (args.length == 2) {
- overrides = mFlagStore.getFlagsForNamespace(args[1]);
- } else {
- overrides = mFlagStore.getFlags();
- }
- if (overrides.isEmpty()) {
- outPw.println("No overrides set");
- } else {
- int longestNamespaceLen = "namespace".length();
- int longestFlagLen = "flag".length();
- int longestValLen = "value".length();
- for (Map.Entry<String, Map<String, String>> namespace : overrides.entrySet()) {
- longestNamespaceLen = Math.max(longestNamespaceLen, namespace.getKey().length());
- for (Map.Entry<String, String> flag : namespace.getValue().entrySet()) {
- longestFlagLen = Math.max(longestFlagLen, flag.getKey().length());
- longestValLen = Math.max(longestValLen, flag.getValue().length());
- }
- }
- outPw.print(String.format("%-" + longestNamespaceLen + "s", "namespace"));
- outPw.print(' ');
- outPw.print(String.format("%-" + longestFlagLen + "s", "flag"));
- outPw.print(' ');
- outPw.println("value");
- for (int i = 0; i < longestNamespaceLen; i++) {
- outPw.print('=');
- }
- outPw.print(' ');
- for (int i = 0; i < longestFlagLen; i++) {
- outPw.print('=');
- }
- outPw.print(' ');
- for (int i = 0; i < longestValLen; i++) {
- outPw.print('=');
- }
- outPw.println();
- for (Map.Entry<String, Map<String, String>> namespace : overrides.entrySet()) {
- for (Map.Entry<String, String> flag : namespace.getValue().entrySet()) {
- outPw.print(
- String.format("%-" + longestNamespaceLen + "s", namespace.getKey()));
- outPw.print(' ');
- outPw.print(String.format("%-" + longestFlagLen + "s", flag.getKey()));
- outPw.print(' ');
- outPw.println(flag.getValue());
- }
- }
- }
- outPw.flush();
- return 0;
- }
-
- private int setCmd(String[] args, PrintWriter outPw, PrintWriter errPw) {
- if (!validateNumArguments(args, 3, args[0], errPw)) {
- errPw.println("Expected `" + args[0] + " <namespace> <name> <value>`");
- errPw.flush();
- return -1;
- }
- mFlagStore.set(args[1], args[2], args[3]);
- outPw.println("Flag " + args[1] + "." + args[2] + " is now " + args[3]);
- outPw.flush();
- return 0;
- }
-
- private int getCmd(String[] args, PrintWriter outPw, PrintWriter errPw) {
- if (!validateNumArguments(args, 2, args[0], errPw)) {
- errPw.println("Expected `" + args[0] + " <namespace> <name>`");
- errPw.flush();
- return -1;
- }
-
- String value = mFlagStore.get(args[1], args[2]);
- outPw.print(args[1] + "." + args[2] + " is ");
- if (value == null || value.isEmpty()) {
- outPw.println("<unset>");
- } else {
- outPw.println("\"" + value.translateEscapes() + "\"");
- }
- outPw.flush();
- return 0;
- }
-
- private int eraseCmd(String[] args, PrintWriter outPw, PrintWriter errPw) {
- if (!validateNumArguments(args, 2, args[0], errPw)) {
- errPw.println("Expected `" + args[0] + " <namespace> <name>`");
- errPw.flush();
- return -1;
- }
- mFlagStore.erase(args[1], args[2]);
- outPw.println("Erased " + args[1] + "." + args[2]);
- return 0;
- }
-
- private int unknownCmd(PrintWriter outPw) {
- outPw.println("This command is unknown.");
- printHelp(outPw);
- outPw.flush();
- return -1;
- }
-
- private boolean validateNumArguments(
- String[] args, int exactly, String cmdName, PrintWriter errPw) {
- return validateNumArguments(args, exactly, exactly, cmdName, errPw);
- }
-
- private boolean validateNumArguments(
- String[] args, int min, int max, String cmdName, PrintWriter errPw) {
- int len = args.length - 1; // Discount the command itself.
- if (len < min) {
- errPw.println(
- "Less than " + min + " arguments provided for \"" + cmdName + "\" command.");
- return false;
- } else if (len > max) {
- errPw.println(
- "More than " + max + " arguments provided for \"" + cmdName + "\" command.");
- return false;
- }
-
- return true;
- }
-}
diff --git a/services/flags/java/com/android/server/flags/GlobalSettingsProxy.java b/services/flags/java/com/android/server/flags/GlobalSettingsProxy.java
deleted file mode 100644
index acb7bb5a49db..000000000000
--- a/services/flags/java/com/android/server/flags/GlobalSettingsProxy.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.provider.Settings;
-
-class GlobalSettingsProxy implements SettingsProxy {
- private final ContentResolver mContentResolver;
-
- GlobalSettingsProxy(ContentResolver contentResolver) {
- mContentResolver = contentResolver;
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mContentResolver;
- }
-
- @Override
- public Uri getUriFor(String name) {
- return Settings.Global.getUriFor(name);
- }
-
- @Override
- public String getStringForUser(String name, int userHandle) {
- return Settings.Global.getStringForUser(mContentResolver, name, userHandle);
- }
-
- @Override
- public boolean putString(String name, String value, boolean overrideableByRestore) {
- throw new UnsupportedOperationException(
- "This method only exists publicly for Settings.System and Settings.Secure");
- }
-
- @Override
- public boolean putStringForUser(String name, String value, int userHandle) {
- return Settings.Global.putStringForUser(mContentResolver, name, value, userHandle);
- }
-
- @Override
- public boolean putStringForUser(String name, String value, String tag, boolean makeDefault,
- int userHandle, boolean overrideableByRestore) {
- return Settings.Global.putStringForUser(
- mContentResolver, name, value, tag, makeDefault, userHandle,
- overrideableByRestore);
- }
-
- @Override
- public boolean putString(String name, String value, String tag, boolean makeDefault) {
- return Settings.Global.putString(mContentResolver, name, value, tag, makeDefault);
- }
-}
diff --git a/services/flags/java/com/android/server/flags/SettingsProxy.java b/services/flags/java/com/android/server/flags/SettingsProxy.java
deleted file mode 100644
index c6e85d5d1dc8..000000000000
--- a/services/flags/java/com/android/server/flags/SettingsProxy.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.provider.Settings;
-
-/**
- * Wrapper class meant to enable hermetic testing of {@link Settings}.
- *
- * Implementations of this class are expected to be constructed with a {@link ContentResolver} or,
- * otherwise have access to an implicit one. All the proxy methods in this class exclude
- * {@link ContentResolver} from their signature and rely on an internally defined one instead.
- *
- * Most methods in the {@link Settings} classes have default implementations defined.
- * Implementations of this interfac need only concern themselves with getting and putting Strings.
- * They should also override any methods for a class they are proxying that _are not_ defined, and
- * throw an appropriate {@link UnsupportedOperationException}. For instance, {@link Settings.Global}
- * does not define {@link #putString(String, String, boolean)}, so an implementation of this
- * interface that proxies through to it should throw an exception when that method is called.
- *
- * This class adds in the following helpers as well:
- * - {@link #getBool(String)}
- * - {@link #putBool(String, boolean)}
- * - {@link #registerContentObserver(Uri, ContentObserver)}
- *
- * ... and similar variations for all of those.
- */
-public interface SettingsProxy {
-
- /**
- * Returns the {@link ContentResolver} this instance uses.
- */
- ContentResolver getContentResolver();
-
- /**
- * Construct the content URI for a particular name/value pair,
- * useful for monitoring changes with a ContentObserver.
- * @param name to look up in the table
- * @return the corresponding content URI, or null if not present
- */
- Uri getUriFor(String name);
-
- /**See {@link Settings.Secure#getString(ContentResolver, String)} */
- String getStringForUser(String name, int userHandle);
-
- /**See {@link Settings.Secure#putString(ContentResolver, String, String, boolean)} */
- boolean putString(String name, String value, boolean overrideableByRestore);
-
- /** See {@link Settings.Secure#putStringForUser(ContentResolver, String, String, int)} */
- boolean putStringForUser(String name, String value, int userHandle);
-
- /**
- * See {@link Settings.Secure#putStringForUser(ContentResolver, String, String, String, boolean,
- * int, boolean)}
- */
- boolean putStringForUser(@NonNull String name, @Nullable String value, @Nullable String tag,
- boolean makeDefault, @UserIdInt int userHandle, boolean overrideableByRestore);
-
- /** See {@link Settings.Secure#putString(ContentResolver, String, String, String, boolean)} */
- boolean putString(@NonNull String name, @Nullable String value, @Nullable String tag,
- boolean makeDefault);
-
- /**
- * Returns the user id for the associated {@link ContentResolver}.
- */
- default int getUserId() {
- return getContentResolver().getUserId();
- }
-
- /** See {@link Settings.Secure#getString(ContentResolver, String)} */
- default String getString(String name) {
- return getStringForUser(name, getUserId());
- }
-
- /** See {@link Settings.Secure#putString(ContentResolver, String, String)} */
- default boolean putString(String name, String value) {
- return putStringForUser(name, value, getUserId());
- }
- /** See {@link Settings.Secure#getIntForUser(ContentResolver, String, int, int)} */
- default int getIntForUser(String name, int def, int userHandle) {
- String v = getStringForUser(name, userHandle);
- try {
- return v != null ? Integer.parseInt(v) : def;
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
- /** See {@link Settings.Secure#getInt(ContentResolver, String)} */
- default int getInt(String name) throws Settings.SettingNotFoundException {
- return getIntForUser(name, getUserId());
- }
-
- /** See {@link Settings.Secure#getIntForUser(ContentResolver, String, int)} */
- default int getIntForUser(String name, int userHandle)
- throws Settings.SettingNotFoundException {
- String v = getStringForUser(name, userHandle);
- try {
- return Integer.parseInt(v);
- } catch (NumberFormatException e) {
- throw new Settings.SettingNotFoundException(name);
- }
- }
-
- /** See {@link Settings.Secure#putInt(ContentResolver, String, int)} */
- default boolean putInt(String name, int value) {
- return putIntForUser(name, value, getUserId());
- }
-
- /** See {@link Settings.Secure#putIntForUser(ContentResolver, String, int, int)} */
- default boolean putIntForUser(String name, int value, int userHandle) {
- return putStringForUser(name, Integer.toString(value), userHandle);
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as a boolean. Note that internally setting values are always
- * stored as strings; this function converts the string to a boolean
- * for you. The default value will be returned if the setting is
- * not defined or not a boolean.
- *
- * @param name The name of the setting to retrieve.
- * @param def Value to return if the setting is not defined.
- *
- * @return The setting's current value, or 'def' if it is not defined
- * or not a valid boolean.
- */
- default boolean getBool(String name, boolean def) {
- return getBoolForUser(name, def, getUserId());
- }
-
- /** See {@link #getBool(String, boolean)}. */
- default boolean getBoolForUser(String name, boolean def, int userHandle) {
- return getIntForUser(name, def ? 1 : 0, userHandle) != 0;
- }
-
- /**
- * Convenience function for retrieving a single settings value
- * as a boolean. Note that internally setting values are always
- * stored as strings; this function converts the string to a boolean
- * for you.
- * <p>
- * This version does not take a default value. If the setting has not
- * been set, or the string value is not a number,
- * it throws {@link Settings.SettingNotFoundException}.
- *
- * @param name The name of the setting to retrieve.
- *
- * @throws Settings.SettingNotFoundException Thrown if a setting by the given
- * name can't be found or the setting value is not a boolean.
- *
- * @return The setting's current value.
- */
- default boolean getBool(String name) throws Settings.SettingNotFoundException {
- return getBoolForUser(name, getUserId());
- }
-
- /** See {@link #getBool(String)}. */
- default boolean getBoolForUser(String name, int userHandle)
- throws Settings.SettingNotFoundException {
- return getIntForUser(name, userHandle) != 0;
- }
-
- /**
- * Convenience function for updating a single settings value as a
- * boolean. This will either create a new entry in the table if the
- * given name does not exist, or modify the value of the existing row
- * with that name. Note that internally setting values are always
- * stored as strings, so this function converts the given value to a
- * string before storing it.
- *
- * @param name The name of the setting to modify.
- * @param value The new value for the setting.
- * @return true if the value was set, false on database errors
- */
- default boolean putBool(String name, boolean value) {
- return putBoolForUser(name, value, getUserId());
- }
-
- /** See {@link #putBool(String, boolean)}. */
- default boolean putBoolForUser(String name, boolean value, int userHandle) {
- return putIntForUser(name, value ? 1 : 0, userHandle);
- }
-
- /** See {@link Settings.Secure#getLong(ContentResolver, String, long)} */
- default long getLong(String name, long def) {
- return getLongForUser(name, def, getUserId());
- }
-
- /** See {@link Settings.Secure#getLongForUser(ContentResolver, String, long, int)} */
- default long getLongForUser(String name, long def, int userHandle) {
- String valString = getStringForUser(name, userHandle);
- long value;
- try {
- value = valString != null ? Long.parseLong(valString) : def;
- } catch (NumberFormatException e) {
- value = def;
- }
- return value;
- }
-
- /** See {@link Settings.Secure#getLong(ContentResolver, String)} */
- default long getLong(String name) throws Settings.SettingNotFoundException {
- return getLongForUser(name, getUserId());
- }
-
- /** See {@link Settings.Secure#getLongForUser(ContentResolver, String, int)} */
- default long getLongForUser(String name, int userHandle)
- throws Settings.SettingNotFoundException {
- String valString = getStringForUser(name, userHandle);
- try {
- return Long.parseLong(valString);
- } catch (NumberFormatException e) {
- throw new Settings.SettingNotFoundException(name);
- }
- }
-
- /** See {@link Settings.Secure#putLong(ContentResolver, String, long)} */
- default boolean putLong(String name, long value) {
- return putLongForUser(name, value, getUserId());
- }
-
- /** See {@link Settings.Secure#putLongForUser(ContentResolver, String, long, int)} */
- default boolean putLongForUser(String name, long value, int userHandle) {
- return putStringForUser(name, Long.toString(value), userHandle);
- }
-
- /** See {@link Settings.Secure#getFloat(ContentResolver, String, float)} */
- default float getFloat(String name, float def) {
- return getFloatForUser(name, def, getUserId());
- }
-
- /** See {@link Settings.Secure#getFloatForUser(ContentResolver, String, int)} */
- default float getFloatForUser(String name, float def, int userHandle) {
- String v = getStringForUser(name, userHandle);
- try {
- return v != null ? Float.parseFloat(v) : def;
- } catch (NumberFormatException e) {
- return def;
- }
- }
-
-
- /** See {@link Settings.Secure#getFloat(ContentResolver, String)} */
- default float getFloat(String name) throws Settings.SettingNotFoundException {
- return getFloatForUser(name, getUserId());
- }
-
- /** See {@link Settings.Secure#getFloatForUser(ContentResolver, String, int)} */
- default float getFloatForUser(String name, int userHandle)
- throws Settings.SettingNotFoundException {
- String v = getStringForUser(name, userHandle);
- if (v == null) {
- throw new Settings.SettingNotFoundException(name);
- }
- try {
- return Float.parseFloat(v);
- } catch (NumberFormatException e) {
- throw new Settings.SettingNotFoundException(name);
- }
- }
-
- /** See {@link Settings.Secure#putFloat(ContentResolver, String, float)} */
- default boolean putFloat(String name, float value) {
- return putFloatForUser(name, value, getUserId());
- }
-
- /** See {@link Settings.Secure#putFloatForUser(ContentResolver, String, float, int)} */
- default boolean putFloatForUser(String name, float value, int userHandle) {
- return putStringForUser(name, Float.toString(value), userHandle);
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
- *
- * Implicitly calls {@link #getUriFor(String)} on the passed in name.
- */
- default void registerContentObserver(String name, ContentObserver settingsObserver) {
- registerContentObserver(getUriFor(name), settingsObserver);
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
- */
- default void registerContentObserver(Uri uri, ContentObserver settingsObserver) {
- registerContentObserverForUser(uri, settingsObserver, getUserId());
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.
- *
- * Implicitly calls {@link #getUriFor(String)} on the passed in name.
- */
- default void registerContentObserver(String name, boolean notifyForDescendants,
- ContentObserver settingsObserver) {
- registerContentObserver(getUriFor(name), notifyForDescendants, settingsObserver);
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
- */
- default void registerContentObserver(Uri uri, boolean notifyForDescendants,
- ContentObserver settingsObserver) {
- registerContentObserverForUser(uri, notifyForDescendants, settingsObserver, getUserId());
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
- *
- * Implicitly calls {@link #getUriFor(String)} on the passed in name.
- */
- default void registerContentObserverForUser(
- String name, ContentObserver settingsObserver, int userHandle) {
- registerContentObserverForUser(
- getUriFor(name), settingsObserver, userHandle);
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
- */
- default void registerContentObserverForUser(
- Uri uri, ContentObserver settingsObserver, int userHandle) {
- registerContentObserverForUser(
- uri, false, settingsObserver, userHandle);
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
- *
- * Implicitly calls {@link #getUriFor(String)} on the passed in name.
- */
- default void registerContentObserverForUser(
- String name, boolean notifyForDescendants, ContentObserver settingsObserver,
- int userHandle) {
- registerContentObserverForUser(
- getUriFor(name), notifyForDescendants, settingsObserver, userHandle);
- }
-
- /**
- * Convenience wrapper around
- * {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
- */
- default void registerContentObserverForUser(
- Uri uri, boolean notifyForDescendants, ContentObserver settingsObserver,
- int userHandle) {
- getContentResolver().registerContentObserver(
- uri, notifyForDescendants, settingsObserver, userHandle);
- }
-
- /** See {@link ContentResolver#unregisterContentObserver(ContentObserver)}. */
- default void unregisterContentObserver(ContentObserver settingsObserver) {
- getContentResolver().unregisterContentObserver(settingsObserver);
- }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7de12790e935..6960da74dd1a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -132,7 +132,6 @@ import com.android.server.display.DisplayManagerService;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.dreams.DreamManagerService;
import com.android.server.emergency.EmergencyAffordanceService;
-import com.android.server.flags.FeatureFlagsService;
import com.android.server.gpu.GpuService;
import com.android.server.grammaticalinflection.GrammaticalInflectionService;
import com.android.server.graphics.fonts.FontManagerService;
@@ -435,6 +434,10 @@ public final class SystemServer implements Dumpable {
+ "OnDevicePersonalizationSystemService$Lifecycle";
private static final String UPDATABLE_DEVICE_CONFIG_SERVICE_CLASS =
"com.android.server.deviceconfig.DeviceConfigInit$Lifecycle";
+ private static final String DEVICE_LOCK_SERVICE_CLASS =
+ "com.android.server.devicelock.DeviceLockService";
+ private static final String DEVICE_LOCK_APEX_PATH =
+ "/apex/com.android.devicelock/javalib/service-devicelock.jar";
private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
@@ -1112,12 +1115,6 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
t.traceEnd();
- // Starts a service for reading runtime flag overrides, and keeping processes
- // in sync with one another.
- t.traceBegin("StartFeatureFlagsService");
- mSystemServiceManager.startService(FeatureFlagsService.class);
- t.traceEnd();
-
// Uri Grants Manager.
t.traceBegin("UriGrantsManagerService");
mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
@@ -2871,6 +2868,13 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(HEALTHCONNECT_MANAGER_SERVICE_CLASS);
t.traceEnd();
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_LOCK)) {
+ t.traceBegin("DeviceLockService");
+ mSystemServiceManager.startServiceFromJar(DEVICE_LOCK_SERVICE_CLASS,
+ DEVICE_LOCK_APEX_PATH);
+ t.traceEnd();
+ }
+
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 4aba30a661ad..f660b42457db 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -16,7 +16,9 @@
package com.android.server.midi;
+import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.content.BroadcastReceiver;
@@ -48,6 +50,7 @@ import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.EventLog;
import android.util.Log;
@@ -81,6 +84,11 @@ import java.util.concurrent.atomic.AtomicLong;
// 2. synchronized (mDeviceConnections)
//TODO Introduce a single lock object to lock the whole state and avoid the requirement above.
+// All users should be able to connect to USB and Bluetooth MIDI devices.
+// All users can create can install an app that provides, a Virtual MIDI Device Service.
+// Users can not open virtual MIDI devices created by other users.
+// getDevices() surfaces devices that can be opened by that user.
+// openDevice() rejects devices that are cannot be opened by that user.
public class MidiService extends IMidiManager.Stub {
public static class Lifecycle extends SystemService {
@@ -97,10 +105,21 @@ public class MidiService extends IMidiManager.Stub {
}
@Override
+ @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS},
+ anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
+ public void onUserStarting(@NonNull TargetUser user) {
+ mMidiService.onStartOrUnlockUser(user, false /* matchDirectBootUnaware */);
+ }
+
+ @Override
+ @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS},
+ anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
public void onUserUnlocking(@NonNull TargetUser user) {
- if (user.getUserIdentifier() == UserHandle.USER_SYSTEM) {
- mMidiService.onUnlockUser();
- }
+ mMidiService.onStartOrUnlockUser(user, true /* matchDirectBootUnaware */);
}
}
@@ -134,6 +153,7 @@ public class MidiService extends IMidiManager.Stub {
private int mNextDeviceId = 1;
private final PackageManager mPackageManager;
+ private final UserManager mUserManager;
private static final String MIDI_LEGACY_STRING = "MIDI 1.0";
private static final String MIDI_UNIVERSAL_STRING = "MIDI 2.0";
@@ -159,21 +179,24 @@ public class MidiService extends IMidiManager.Stub {
private final HashSet<ParcelUuid> mNonMidiUUIDs = new HashSet<ParcelUuid>();
// PackageMonitor for listening to package changes
+ // uid is the uid of the package so use getChangingUserId() to fetch the userId.
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
+ @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public void onPackageAdded(String packageName, int uid) {
- addPackageDeviceServers(packageName);
+ addPackageDeviceServers(packageName, getChangingUserId());
}
@Override
+ @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public void onPackageModified(String packageName) {
- removePackageDeviceServers(packageName);
- addPackageDeviceServers(packageName);
+ removePackageDeviceServers(packageName, getChangingUserId());
+ addPackageDeviceServers(packageName, getChangingUserId());
}
@Override
public void onPackageRemoved(String packageName, int uid) {
- removePackageDeviceServers(packageName);
+ removePackageDeviceServers(packageName, getChangingUserId());
}
};
@@ -202,6 +225,10 @@ public class MidiService extends IMidiManager.Stub {
return mUid;
}
+ private int getUserId() {
+ return UserHandle.getUserId(mUid);
+ }
+
public void addListener(IMidiDeviceListener listener) {
if (mListeners.size() >= MAX_LISTENERS_PER_CLIENT) {
throw new SecurityException(
@@ -219,8 +246,12 @@ public class MidiService extends IMidiManager.Stub {
}
}
- public void addDeviceConnection(Device device, IMidiDeviceOpenCallback callback) {
- Log.d(TAG, "addDeviceConnection() device:" + device);
+ @RequiresPermission(anyOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ Manifest.permission.INTERACT_ACROSS_PROFILES})
+ public void addDeviceConnection(Device device, IMidiDeviceOpenCallback callback,
+ int userId) {
+ Log.d(TAG, "addDeviceConnection() device:" + device + " userId:" + userId);
if (mDeviceConnections.size() >= MAX_CONNECTIONS_PER_CLIENT) {
Log.i(TAG, "too many MIDI connections for UID = " + mUid);
throw new SecurityException(
@@ -228,7 +259,7 @@ public class MidiService extends IMidiManager.Stub {
}
DeviceConnection connection = new DeviceConnection(device, this, callback);
mDeviceConnections.put(connection.getToken(), connection);
- device.addDeviceConnection(connection);
+ device.addDeviceConnection(connection, userId);
}
// called from MidiService.closeDevice()
@@ -251,8 +282,8 @@ public class MidiService extends IMidiManager.Stub {
}
public void deviceAdded(Device device) {
- // ignore private devices that our client cannot access
- if (!device.isUidAllowed(mUid)) return;
+ // ignore devices that our client cannot access
+ if (!device.isUidAllowed(mUid) || !device.isUserIdAllowed(getUserId())) return;
MidiDeviceInfo deviceInfo = device.getDeviceInfo();
try {
@@ -265,8 +296,8 @@ public class MidiService extends IMidiManager.Stub {
}
public void deviceRemoved(Device device) {
- // ignore private devices that our client cannot access
- if (!device.isUidAllowed(mUid)) return;
+ // ignore devices that our client cannot access
+ if (!device.isUidAllowed(mUid) || !device.isUserIdAllowed(getUserId())) return;
MidiDeviceInfo deviceInfo = device.getDeviceInfo();
try {
@@ -279,8 +310,8 @@ public class MidiService extends IMidiManager.Stub {
}
public void deviceStatusChanged(Device device, MidiDeviceStatus status) {
- // ignore private devices that our client cannot access
- if (!device.isUidAllowed(mUid)) return;
+ // ignore devices that our client cannot access
+ if (!device.isUidAllowed(mUid) || !device.isUserIdAllowed(getUserId())) return;
try {
for (IMidiDeviceListener listener : mListeners.values()) {
@@ -354,6 +385,8 @@ public class MidiService extends IMidiManager.Stub {
private final ServiceInfo mServiceInfo;
// UID of device implementation
private final int mUid;
+ // User Id of the app. Only used for virtual devices
+ private final int mUserId;
// ServiceConnection for implementing Service (virtual devices only)
// mServiceConnection is non-null when connected or attempting to connect to the service
@@ -375,19 +408,24 @@ public class MidiService extends IMidiManager.Stub {
private AtomicInteger mTotalOutputBytes = new AtomicInteger();
public Device(IMidiDeviceServer server, MidiDeviceInfo deviceInfo,
- ServiceInfo serviceInfo, int uid) {
+ ServiceInfo serviceInfo, int uid, int userId) {
mDeviceInfo = deviceInfo;
mServiceInfo = serviceInfo;
mUid = uid;
+ mUserId = userId;
mBluetoothDevice = (BluetoothDevice)deviceInfo.getProperties().getParcelable(
MidiDeviceInfo.PROPERTY_BLUETOOTH_DEVICE, android.bluetooth.BluetoothDevice.class);;
setDeviceServer(server);
}
+ @RequiresPermission(anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
public Device(BluetoothDevice bluetoothDevice) {
mBluetoothDevice = bluetoothDevice;
mServiceInfo = null;
mUid = mBluetoothServiceUid;
+ mUserId = mUserManager.getMainUser().getIdentifier();
}
private void setDeviceServer(IMidiDeviceServer server) {
@@ -468,11 +506,22 @@ public class MidiService extends IMidiManager.Stub {
return mUid;
}
+ public int getUserId() {
+ return mUserId;
+ }
+
public boolean isUidAllowed(int uid) {
return (!mDeviceInfo.isPrivate() || mUid == uid);
}
- public void addDeviceConnection(DeviceConnection connection) {
+ public boolean isUserIdAllowed(int userId) {
+ return (mDeviceInfo.getType() != MidiDeviceInfo.TYPE_VIRTUAL || mUserId == userId);
+ }
+
+ @RequiresPermission(anyOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ Manifest.permission.INTERACT_ACROSS_PROFILES})
+ public void addDeviceConnection(DeviceConnection connection, int userId) {
Log.d(TAG, "addDeviceConnection() [A] connection:" + connection);
synchronized (mDeviceConnections) {
mDeviceConnectionsAdded.incrementAndGet();
@@ -537,8 +586,8 @@ public class MidiService extends IMidiManager.Stub {
new ComponentName(mServiceInfo.packageName, mServiceInfo.name));
}
- if (!mContext.bindService(intent, mServiceConnection,
- Context.BIND_AUTO_CREATE)) {
+ if (!mContext.bindServiceAsUser(intent, mServiceConnection,
+ Context.BIND_AUTO_CREATE, UserHandle.of(mUserId))) {
Log.e(TAG, "Unable to bind service: " + intent);
setDeviceServer(null);
mServiceConnection = null;
@@ -886,6 +935,8 @@ public class MidiService extends IMidiManager.Stub {
public MidiService(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
// TEMPORARY - Disable BTL-MIDI
//FIXME - b/25689266
@@ -913,32 +964,41 @@ public class MidiService extends IMidiManager.Stub {
// mNonMidiUUIDs.add(BluetoothUuid.BATTERY);
}
- private void onUnlockUser() {
- mPackageMonitor.register(mContext, null, true);
-
+ @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS},
+ anyOf = {Manifest.permission.QUERY_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.MANAGE_USERS})
+ private void onStartOrUnlockUser(TargetUser user, boolean matchDirectBootUnaware) {
+ Log.d(TAG, "onStartOrUnlockUser " + user.getUserIdentifier() + " matchDirectBootUnaware: "
+ + matchDirectBootUnaware);
Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE);
- List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(intent,
- PackageManager.GET_META_DATA);
+ int resolveFlags = PackageManager.GET_META_DATA;
+ if (matchDirectBootUnaware) {
+ resolveFlags |= PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+ }
+ List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServicesAsUser(intent,
+ resolveFlags, user.getUserIdentifier());
if (resolveInfos != null) {
int count = resolveInfos.size();
for (int i = 0; i < count; i++) {
ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
if (serviceInfo != null) {
- addPackageDeviceServer(serviceInfo);
+ addPackageDeviceServer(serviceInfo, user.getUserIdentifier());
}
}
}
- PackageInfo info;
- try {
- info = mPackageManager.getPackageInfo(MidiManager.BLUETOOTH_MIDI_SERVICE_PACKAGE, 0);
- } catch (PackageManager.NameNotFoundException e) {
- info = null;
- }
- if (info != null && info.applicationInfo != null) {
- mBluetoothServiceUid = info.applicationInfo.uid;
- } else {
- mBluetoothServiceUid = -1;
+ if (user.getUserIdentifier() == mUserManager.getMainUser().getIdentifier()) {
+ PackageInfo info;
+ try {
+ info = mPackageManager.getPackageInfoAsUser(
+ MidiManager.BLUETOOTH_MIDI_SERVICE_PACKAGE, 0, user.getUserIdentifier());
+ } catch (PackageManager.NameNotFoundException e) {
+ info = null;
+ }
+ if (info != null && info.applicationInfo != null) {
+ mBluetoothServiceUid = info.applicationInfo.uid;
+ }
}
}
@@ -960,10 +1020,11 @@ public class MidiService extends IMidiManager.Stub {
// Inform listener of the status of all known devices.
private void updateStickyDeviceStatus(int uid, IMidiDeviceListener listener) {
+ int userId = UserHandle.getUserId(uid);
synchronized (mDevicesByInfo) {
for (Device device : mDevicesByInfo.values()) {
- // ignore private devices that our client cannot access
- if (device.isUidAllowed(uid)) {
+ // ignore devices that our client cannot access
+ if (device.isUidAllowed(uid) && device.isUserIdAllowed(userId)) {
try {
MidiDeviceStatus status = device.getDeviceStatus();
if (status != null) {
@@ -989,10 +1050,11 @@ public class MidiService extends IMidiManager.Stub {
public MidiDeviceInfo[] getDevicesForTransport(int transport) {
ArrayList<MidiDeviceInfo> deviceInfos = new ArrayList<MidiDeviceInfo>();
int uid = Binder.getCallingUid();
+ int userId = getCallingUserId();
synchronized (mDevicesByInfo) {
for (Device device : mDevicesByInfo.values()) {
- if (device.isUidAllowed(uid)) {
+ if (device.isUidAllowed(uid) && device.isUserIdAllowed(userId)) {
// UMP devices have protocols that are not PROTOCOL_UNKNOWN
if (transport == MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS) {
if (device.getDeviceInfo().getDefaultProtocol()
@@ -1029,6 +1091,9 @@ public class MidiService extends IMidiManager.Stub {
if (!device.isUidAllowed(Binder.getCallingUid())) {
throw new SecurityException("Attempt to open private device with wrong UID");
}
+ if (!device.isUserIdAllowed(getCallingUserId())) {
+ throw new SecurityException("Attempt to open virtual device with wrong user id");
+ }
}
if (deviceInfo.getType() == MidiDeviceInfo.TYPE_USB) {
@@ -1044,7 +1109,7 @@ public class MidiService extends IMidiManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
Log.i(TAG, "addDeviceConnection() [B] device:" + device);
- client.addDeviceConnection(device, callback);
+ client.addDeviceConnection(device, callback, getCallingUserId());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1106,7 +1171,7 @@ public class MidiService extends IMidiManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
Log.i(TAG, "addDeviceConnection() [C] device:" + device);
- client.addDeviceConnection(device, callback);
+ client.addDeviceConnection(device, callback, getCallingUserId());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1124,6 +1189,7 @@ public class MidiService extends IMidiManager.Stub {
int numOutputPorts, String[] inputPortNames, String[] outputPortNames,
Bundle properties, int type, int defaultProtocol) {
int uid = Binder.getCallingUid();
+ int userId = getCallingUserId();
if (type == MidiDeviceInfo.TYPE_USB && uid != Process.SYSTEM_UID) {
throw new SecurityException("only system can create USB devices");
} else if (type == MidiDeviceInfo.TYPE_BLUETOOTH && uid != mBluetoothServiceUid) {
@@ -1133,7 +1199,7 @@ public class MidiService extends IMidiManager.Stub {
synchronized (mDevicesByInfo) {
return addDeviceLocked(type, numInputPorts, numOutputPorts, inputPortNames,
outputPortNames, properties, server, null, false, uid,
- defaultProtocol);
+ defaultProtocol, userId);
}
}
@@ -1210,7 +1276,8 @@ public class MidiService extends IMidiManager.Stub {
private MidiDeviceInfo addDeviceLocked(int type, int numInputPorts, int numOutputPorts,
String[] inputPortNames, String[] outputPortNames, Bundle properties,
IMidiDeviceServer server, ServiceInfo serviceInfo,
- boolean isPrivate, int uid, int defaultProtocol) {
+ boolean isPrivate, int uid, int defaultProtocol, int userId) {
+ Log.d(TAG, "addDeviceLocked()" + uid + " type:" + type);
// Limit the number of devices per app.
int deviceCountForApp = 0;
@@ -1250,7 +1317,7 @@ public class MidiService extends IMidiManager.Stub {
}
}
if (device == null) {
- device = new Device(server, deviceInfo, serviceInfo, uid);
+ device = new Device(server, deviceInfo, serviceInfo, uid, userId);
}
mDevicesByInfo.put(deviceInfo, device);
if (bluetoothDevice != null) {
@@ -1281,12 +1348,14 @@ public class MidiService extends IMidiManager.Stub {
}
}
- private void addPackageDeviceServers(String packageName) {
+ @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
+ private void addPackageDeviceServers(String packageName, int userId) {
PackageInfo info;
try {
- info = mPackageManager.getPackageInfo(packageName,
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ info = mPackageManager.getPackageInfoAsUser(packageName,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "handlePackageUpdate could not find package " + packageName, e);
return;
@@ -1295,13 +1364,14 @@ public class MidiService extends IMidiManager.Stub {
ServiceInfo[] services = info.services;
if (services == null) return;
for (int i = 0; i < services.length; i++) {
- addPackageDeviceServer(services[i]);
+ addPackageDeviceServer(services[i], userId);
}
}
private static final String[] EMPTY_STRING_ARRAY = new String[0];
- private void addPackageDeviceServer(ServiceInfo serviceInfo) {
+ private void addPackageDeviceServer(ServiceInfo serviceInfo, int userId) {
+ Log.d(TAG, "addPackageDeviceServer()" + userId);
XmlResourceParser parser = null;
try {
@@ -1404,8 +1474,8 @@ public class MidiService extends IMidiManager.Stub {
int uid;
try {
- ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
- serviceInfo.packageName, 0);
+ ApplicationInfo appInfo = mPackageManager.getApplicationInfoAsUser(
+ serviceInfo.packageName, 0, userId);
uid = appInfo.uid;
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "could not fetch ApplicationInfo for "
@@ -1419,7 +1489,7 @@ public class MidiService extends IMidiManager.Stub {
inputPortNames.toArray(EMPTY_STRING_ARRAY),
outputPortNames.toArray(EMPTY_STRING_ARRAY),
properties, null, serviceInfo, isPrivate, uid,
- MidiDeviceInfo.PROTOCOL_UNKNOWN);
+ MidiDeviceInfo.PROTOCOL_UNKNOWN, userId);
}
// setting properties to null signals that we are no longer
// processing a <device>
@@ -1437,12 +1507,13 @@ public class MidiService extends IMidiManager.Stub {
}
}
- private void removePackageDeviceServers(String packageName) {
+ private void removePackageDeviceServers(String packageName, int userId) {
synchronized (mDevicesByInfo) {
Iterator<Device> iterator = mDevicesByInfo.values().iterator();
while (iterator.hasNext()) {
Device device = iterator.next();
- if (packageName.equals(device.getPackageName())) {
+ if (packageName.equals(device.getPackageName())
+ && (device.getUserId() == userId)) {
iterator.remove();
removeDeviceLocked(device);
}
@@ -1571,4 +1642,11 @@ public class MidiService extends IMidiManager.Stub {
String extractUsbDeviceTag(String propertyName) {
return propertyName.substring(propertyName.length() - MIDI_LEGACY_STRING.length());
}
+
+ /**
+ * @return the user id of the calling user.
+ */
+ private int getCallingUserId() {
+ return UserHandle.getUserId(Binder.getCallingUid());
+ }
}
diff --git a/services/tests/InputMethodSystemServerTests/AndroidManifest.xml b/services/tests/InputMethodSystemServerTests/AndroidManifest.xml
index bef56cec3385..212ec14b4939 100644
--- a/services/tests/InputMethodSystemServerTests/AndroidManifest.xml
+++ b/services/tests/InputMethodSystemServerTests/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.frameworks.inputmethodtests">
+ <uses-sdk android:targetSdkVersion="31" />
<queries>
<intent>
<action android:name="android.view.InputMethod" />
diff --git a/services/tests/InputMethodSystemServerTests/TEST_MAPPING b/services/tests/InputMethodSystemServerTests/TEST_MAPPING
index cedbfd2b2dde..77e32a776d57 100644
--- a/services/tests/InputMethodSystemServerTests/TEST_MAPPING
+++ b/services/tests/InputMethodSystemServerTests/TEST_MAPPING
@@ -9,16 +9,5 @@
{"exclude-annotation": "org.junit.Ignore"}
]
}
- ],
- "postsubmit": [
- {
- "name": "FrameworksImeTests",
- "options": [
- {"include-filter": "com.android.inputmethodservice"},
- {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.FlakyTest"},
- {"exclude-annotation": "org.junit.Ignore"}
- ]
- }
]
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml
index b7de74987eb8..0104f7142bea 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/AndroidManifest.xml
@@ -18,6 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.inputmethod.imetests">
+ <uses-sdk android:targetSdkVersion="31" />
+
<!-- Permissions required for granting and logging -->
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index e8acb067f625..898658e759c0 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -20,8 +20,6 @@ import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.fail;
-
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
@@ -47,7 +45,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -59,9 +56,9 @@ public class InputMethodServiceTest {
private static final String EDIT_TEXT_DESC = "Input box";
private static final long TIMEOUT_IN_SECONDS = 3;
private static final String ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD =
- "settings put secure " + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD + " 1";
+ "settings put secure show_ime_with_hard_keyboard 1";
private static final String DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD =
- "settings put secure " + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD + " 0";
+ "settings put secure show_ime_with_hard_keyboard 0";
private Instrumentation mInstrumentation;
private UiDevice mUiDevice;
@@ -85,19 +82,29 @@ public class InputMethodServiceTest {
mUiDevice.freezeRotation();
mUiDevice.setOrientationNatural();
// Waits for input binding ready.
- eventually(() -> {
- mInputMethodService =
- InputMethodServiceWrapper.getInputMethodServiceWrapperForTesting();
- assertThat(mInputMethodService).isNotNull();
-
- // The editor won't bring up keyboard by default.
- assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
- assertThat(mInputMethodService.getCurrentInputViewStarted()).isFalse();
- });
- // Save the original value of show_ime_with_hard_keyboard from Settings.
+ eventually(
+ () -> {
+ mInputMethodService =
+ InputMethodServiceWrapper.getInputMethodServiceWrapperForTesting();
+ assertThat(mInputMethodService).isNotNull();
+
+ // The editor won't bring up keyboard by default.
+ assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
+ assertThat(mInputMethodService.getCurrentInputViewStarted()).isFalse();
+ });
+ // Save the original value of show_ime_with_hard_keyboard in Settings.
mShowImeWithHardKeyboardEnabled = Settings.Secure.getInt(
mInputMethodService.getContentResolver(),
Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0;
+ // Disable showing Ime with hard keyboard because it is the precondition the for most test
+ // cases
+ if (mShowImeWithHardKeyboardEnabled) {
+ executeShellCommand(DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
+ }
+ mInputMethodService.getResources().getConfiguration().keyboard =
+ Configuration.KEYBOARD_NOKEYS;
+ mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
+ Configuration.HARDKEYBOARDHIDDEN_YES;
}
@After
@@ -105,141 +112,82 @@ public class InputMethodServiceTest {
mUiDevice.unfreezeRotation();
executeShellCommand("ime disable " + mInputMethodId);
// Change back the original value of show_ime_with_hard_keyboard in Settings.
- executeShellCommand(mShowImeWithHardKeyboardEnabled
- ? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
+ executeShellCommand(mShowImeWithHardKeyboardEnabled ? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
: DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
}
- /**
- * This checks that the IME can be shown and hidden by user actions
- * (i.e. tapping on an EditText, tapping the Home button).
- */
@Test
- public void testShowHideKeyboard_byUserAction() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
+ public void testShowHideKeyboard_byUserAction() throws InterruptedException {
// Performs click on editor box to bring up the soft keyboard.
Log.i(TAG, "Click on EditText.");
- verifyInputViewStatus(
- () -> clickOnEditorText(),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ verifyInputViewStatus(() -> clickOnEditorText(), true /* inputViewStarted */);
- // Press home key to hide soft keyboard.
- Log.i(TAG, "Press home");
+ // Press back key to hide soft keyboard.
+ Log.i(TAG, "Press back");
verifyInputViewStatus(
- () -> assertThat(mUiDevice.pressHome()).isTrue(),
- true /* expected */,
- false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ () -> assertThat(mUiDevice.pressHome()).isTrue(), false /* inputViewStarted */);
}
- /**
- * This checks that the IME can be shown and hidden using the WindowInsetsController APIs.
- */
@Test
- public void testShowHideKeyboard_byApi() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
+ public void testShowHideKeyboard_byApi() throws InterruptedException {
// Triggers to show IME via public API.
verifyInputViewStatus(
() -> assertThat(mActivity.showImeWithWindowInsetsController()).isTrue(),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
// Triggers to hide IME via public API.
verifyInputViewStatusOnMainSync(
- () -> assertThat(mActivity.hideImeWithWindowInsetsController()).isTrue(),
- true /* expected */,
+ () -> assertThat(mActivity.hideImeWithInputMethodManager(0 /* flags */)).isTrue(),
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
- /**
- * This checks the result of calling IMS#requestShowSelf and IMS#requestHideSelf.
- */
@Test
- public void testShowHideSelf() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- // IME request to show itself without any flags, expect shown.
+ public void testShowHideSelf() throws InterruptedException {
+ // IME requests to show itself without any flags: expect shown.
Log.i(TAG, "Call IMS#requestShowSelf(0)");
verifyInputViewStatusOnMainSync(
- () -> mInputMethodService.requestShowSelf(0 /* flags */),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ () -> mInputMethodService.requestShowSelf(0), true /* inputViewStarted */);
- // IME request to hide itself with flag HIDE_IMPLICIT_ONLY, expect not hide (shown).
+ // IME requests to hide itself with flag: HIDE_IMPLICIT_ONLY, expect not hide (shown).
Log.i(TAG, "Call IMS#requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY)");
verifyInputViewStatusOnMainSync(
() -> mInputMethodService.requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY),
- false /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- // IME request to hide itself without any flags, expect hidden.
+ // IME request to hide itself without any flags: expect hidden.
Log.i(TAG, "Call IMS#requestHideSelf(0)");
verifyInputViewStatusOnMainSync(
- () -> mInputMethodService.requestHideSelf(0 /* flags */),
- true /* expected */,
- false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ () -> mInputMethodService.requestHideSelf(0), false /* inputViewStarted */);
- // IME request to show itself with flag SHOW_IMPLICIT, expect shown.
+ // IME request to show itself with flag SHOW_IMPLICIT: expect shown.
Log.i(TAG, "Call IMS#requestShowSelf(InputMethodManager.SHOW_IMPLICIT)");
verifyInputViewStatusOnMainSync(
() -> mInputMethodService.requestShowSelf(InputMethodManager.SHOW_IMPLICIT),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- // IME request to hide itself with flag HIDE_IMPLICIT_ONLY, expect hidden.
+ // IME request to hide itself with flag: HIDE_IMPLICIT_ONLY, expect hidden.
Log.i(TAG, "Call IMS#requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY)");
verifyInputViewStatusOnMainSync(
() -> mInputMethodService.requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY),
- true /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
- /**
- * This checks the return value of IMS#onEvaluateInputViewShown,
- * when show_ime_with_hard_keyboard is enabled.
- */
@Test
public void testOnEvaluateInputViewShown_showImeWithHardKeyboard() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
+ executeShellCommand(ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
+ mInstrumentation.waitForIdleSync();
+ // Simulate connecting a hard keyboard
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
-
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_NOKEYS;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_NO;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_QWERTY;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
}
- /**
- * This checks the return value of IMSonEvaluateInputViewShown,
- * when show_ime_with_hard_keyboard is disabled.
- */
@Test
- public void testOnEvaluateInputViewShown_disableShowImeWithHardKeyboard() throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
+ public void testOnEvaluateInputViewShown_disableShowImeWithHardKeyboard() {
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -248,8 +196,6 @@ public class InputMethodServiceTest {
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_NOKEYS;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_NO;
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
mInputMethodService.getResources().getConfiguration().keyboard =
@@ -259,386 +205,149 @@ public class InputMethodServiceTest {
eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
}
- /**
- * This checks that any (implicit or explicit) show request,
- * when IMS#onEvaluateInputViewShown returns false, results in the IME not being shown.
- */
@Test
public void testShowSoftInput_disableShowImeWithHardKeyboard() throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hard keyboard
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
-
// When InputMethodService#onEvaluateInputViewShown() returns false, the Ime should not be
// shown no matter what the show flag is.
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
- false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
-
verifyInputViewStatusOnMainSync(
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
- /**
- * This checks that an explicit show request results in the IME being shown.
- */
@Test
public void testShowSoftInputExplicitly() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
// When InputMethodService#onEvaluateInputViewShown() returns true and flag is EXPLICIT, the
// Ime should be shown.
verifyInputViewStatusOnMainSync(
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
}
- /**
- * This checks that an implicit show request results in the IME being shown.
- */
@Test
public void testShowSoftInputImplicitly() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- // When InputMethodService#onEvaluateInputViewShown() returns true and flag is IMPLICIT,
- // the IME should be shown.
+ // When InputMethodService#onEvaluateInputViewShown() returns true and flag is IMPLICIT, the
+ // Ime should be shown.
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- }
-
- /**
- * This checks that an explicit show request when the IME is not previously shown,
- * and it should be shown in fullscreen mode, results in the IME being shown.
- */
- @Test
- public void testShowSoftInputExplicitly_fullScreenMode() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- // Set orientation landscape to enable fullscreen mode.
- setOrientation(2);
- eventually(() -> assertThat(mUiDevice.isNaturalOrientation()).isFalse());
- // Wait for the TestActivity to be recreated.
- eventually(() ->
- assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
- // Get the new TestActivity.
- mActivity = TestActivity.getLastCreatedInstance();
- assertThat(mActivity).isNotNull();
- InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
- // Wait for the new EditText to be served by InputMethodManager.
- eventually(() -> assertThat(
- imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
-
- verifyInputViewStatusOnMainSync(() -> assertThat(
- mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
}
- /**
- * This checks that an implicit show request when the IME is not previously shown,
- * and it should be shown in fullscreen mode, results in the IME not being shown.
- */
@Test
public void testShowSoftInputImplicitly_fullScreenMode() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- // Set orientation landscape to enable fullscreen mode.
+ // When keyboard is off, InputMethodService#onEvaluateInputViewShown returns true, flag is
+ // IMPLICIT and InputMethodService#onEvaluateFullScreenMode returns true, the Ime should not
+ // be shown.
setOrientation(2);
eventually(() -> assertThat(mUiDevice.isNaturalOrientation()).isFalse());
- // Wait for the TestActivity to be recreated.
+ // Wait for the TestActivity to be recreated
eventually(() ->
assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
- // Get the new TestActivity.
+ // Get the new TestActivity
mActivity = TestActivity.getLastCreatedInstance();
assertThat(mActivity).isNotNull();
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
- // Wait for the new EditText to be served by InputMethodManager.
- eventually(() -> assertThat(
- imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
-
+ // Wait for the new EditText to be served by InputMethodManager
+ eventually(() ->
+ assertThat(imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
- false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
- /**
- * This checks that an explicit show request when a hard keyboard is connected,
- * results in the IME being shown.
- */
- @Test
- public void testShowSoftInputExplicitly_withHardKeyboard() throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
- // Simulate connecting a hard keyboard.
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_QWERTY;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
- verifyInputViewStatusOnMainSync(() -> assertThat(
- mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- }
-
- /**
- * This checks that an implicit show request when a hard keyboard is connected,
- * results in the IME not being shown.
- */
@Test
public void testShowSoftInputImplicitly_withHardKeyboard() throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
- // Simulate connecting a hard keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
+ // When connecting to a hard keyboard and the flag is IMPLICIT, the Ime should not be shown.
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
- false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
- /**
- * This checks that an explicit show request followed by connecting a hard keyboard
- * and a configuration change, still results in the IME being shown.
- */
@Test
- public void testShowSoftInputExplicitly_thenConfigurationChanged() throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
- // Start with no hard keyboard.
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_NOKEYS;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
+ public void testConfigurationChanged_withKeyboardShownExplicitly() throws InterruptedException {
verifyInputViewStatusOnMainSync(
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
-
- // Simulate connecting a hard keyboard.
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_QWERTY;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
// Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
mInputMethodService.getResources().getConfiguration().orientation =
Configuration.ORIENTATION_LANDSCAPE;
-
verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
mInputMethodService.getResources().getConfiguration()),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
}
- /**
- * This checks that an implicit show request followed by connecting a hard keyboard
- * and a configuration change, does not trigger IMS#onFinishInputView,
- * but results in the IME being hidden.
- */
@Test
- public void testShowSoftInputImplicitly_thenConfigurationChanged() throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
- // Start with no hard keyboard.
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_NOKEYS;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
+ public void testConfigurationChanged_withKeyboardShownImplicitly() throws InterruptedException {
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
- true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
-
- // Simulate connecting a hard keyboard.
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_QWERTY;
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
// Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
mInputMethodService.getResources().getConfiguration().orientation =
Configuration.ORIENTATION_LANDSCAPE;
+ mInputMethodService.getResources().getConfiguration().keyboard =
+ Configuration.KEYBOARD_QWERTY;
// Normally, IMS#onFinishInputView will be called when finishing the input view by the user.
// But if IMS#hideWindow is called when receiving a new configuration change, we don't
// expect that it's user-driven to finish the lifecycle of input view with
// IMS#onFinishInputView, because the input view will be re-initialized according to the
- // last #mShowInputRequested state. So in this case we treat the input view as still alive.
+ // last mShowSoftRequested state. So in this case we treat the input view is still alive.
verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
- mInputMethodService.getResources().getConfiguration()),
- true /* expected */,
+ mInputMethodService.getResources().getConfiguration()),
true /* inputViewStarted */);
assertThat(mInputMethodService.isInputViewShown()).isFalse();
}
- /**
- * This checks that an explicit show request directly followed by an implicit show request,
- * while a hardware keyboard is connected, still results in the IME being shown
- * (i.e. the implicit show request is treated as explicit).
- */
- @Test
- public void testShowSoftInputExplicitly_thenShowSoftInputImplicitly_withHardKeyboard()
- throws Exception {
- setShowImeWithHardKeyboard(false /* enabled */);
-
- // Simulate connecting a hard keyboard.
- mInputMethodService.getResources().getConfiguration().keyboard =
- Configuration.KEYBOARD_QWERTY;
- mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
- Configuration.HARDKEYBOARDHIDDEN_YES;
-
- // Explicit show request.
- verifyInputViewStatusOnMainSync(() -> assertThat(
- mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
-
- // Implicit show request.
- verifyInputViewStatusOnMainSync(() -> assertThat(
- mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
- false /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
-
- // Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
- // This should now consider the implicit show request, but keep the state from the
- // explicit show request, and thus not hide the keyboard.
- verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
- mInputMethodService.getResources().getConfiguration()),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- }
-
- /**
- * This checks that a forced show request directly followed by an explicit show request,
- * and then a hide not always request, still results in the IME being shown
- * (i.e. the explicit show request retains the forced state).
- */
- @Test
- public void testShowSoftInputForced_testShowSoftInputExplicitly_thenHideSoftInputNotAlways()
- throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- verifyInputViewStatusOnMainSync(() -> assertThat(
- mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_FORCED)).isTrue(),
- true /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
-
- verifyInputViewStatusOnMainSync(() -> assertThat(
- mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- false /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
-
- verifyInputViewStatusOnMainSync(() ->
- mActivity.hideImeWithInputMethodManager(InputMethodManager.HIDE_NOT_ALWAYS),
- false /* expected */,
- true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- }
-
- /**
- * This checks that the IME fullscreen mode state is updated after changing orientation.
- */
- @Test
- public void testFullScreenMode() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- Log.i(TAG, "Set orientation natural");
- verifyFullscreenMode(() -> setOrientation(0),
- false /* expected */,
- true /* orientationPortrait */);
-
- Log.i(TAG, "Set orientation left");
- verifyFullscreenMode(() -> setOrientation(1),
- true /* expected */,
- false /* orientationPortrait */);
-
- Log.i(TAG, "Set orientation right");
- verifyFullscreenMode(() -> setOrientation(2),
- false /* expected */,
- false /* orientationPortrait */);
- }
-
- private void verifyInputViewStatus(
- Runnable runnable, boolean expected, boolean inputViewStarted)
+ private void verifyInputViewStatus(Runnable runnable, boolean inputViewStarted)
throws InterruptedException {
- verifyInputViewStatusInternal(runnable, expected, inputViewStarted,
- false /* runOnMainSync */);
+ verifyInputViewStatusInternal(runnable, inputViewStarted, false /*runOnMainSync*/);
}
- private void verifyInputViewStatusOnMainSync(
- Runnable runnable, boolean expected, boolean inputViewStarted)
+ private void verifyInputViewStatusOnMainSync(Runnable runnable, boolean inputViewStarted)
throws InterruptedException {
- verifyInputViewStatusInternal(runnable, expected, inputViewStarted,
- true /* runOnMainSync */);
+ verifyInputViewStatusInternal(runnable, inputViewStarted, true /*runOnMainSync*/);
}
- /**
- * Verifies the status of the Input View after executing the given runnable.
- *
- * @param runnable the runnable to execute for showing or hiding the IME.
- * @param expected whether the runnable is expected to trigger the signal.
- * @param inputViewStarted the expected state of the Input View after executing the runnable.
- * @param runOnMainSync whether to execute the runnable on the main thread.
- */
private void verifyInputViewStatusInternal(
- Runnable runnable, boolean expected, boolean inputViewStarted, boolean runOnMainSync)
+ Runnable runnable, boolean inputViewStarted, boolean runOnMainSync)
throws InterruptedException {
CountDownLatch signal = new CountDownLatch(1);
mInputMethodService.setCountDownLatchForTesting(signal);
- // Runnable to trigger onStartInputView() / onFinishInputView() / onConfigurationChanged()
+ // Runnable to trigger onStartInputView()/ onFinishInputView()
if (runOnMainSync) {
mInstrumentation.runOnMainSync(runnable);
} else {
runnable.run();
}
+ // Waits for onStartInputView() to finish.
mInstrumentation.waitForIdleSync();
- boolean completed = signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
- if (expected && !completed) {
- fail("Timed out waiting for"
- + " onStartInputView() / onFinishInputView() / onConfigurationChanged()");
- } else if (!expected && completed) {
- fail("Unexpected call"
- + " onStartInputView() / onFinishInputView() / onConfigurationChanged()");
- }
+ signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
// Input is not finished.
assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
assertThat(mInputMethodService.getCurrentInputViewStarted()).isEqualTo(inputViewStarted);
}
+ @Test
+ public void testFullScreenMode() throws Exception {
+ Log.i(TAG, "Set orientation natural");
+ verifyFullscreenMode(() -> setOrientation(0), true /* orientationPortrait */);
+
+ Log.i(TAG, "Set orientation left");
+ verifyFullscreenMode(() -> setOrientation(1), false /* orientationPortrait */);
+
+ Log.i(TAG, "Set orientation right");
+ verifyFullscreenMode(() -> setOrientation(2), false /* orientationPortrait */);
+ }
+
private void setOrientation(int orientation) {
// Simple wrapper for catching RemoteException.
try {
@@ -657,15 +366,7 @@ public class InputMethodServiceTest {
}
}
- /**
- * Verifies the IME fullscreen mode state after executing the given runnable.
- *
- * @param runnable the runnable to execute for setting the orientation.
- * @param expected whether the runnable is expected to trigger the signal.
- * @param orientationPortrait whether the orientation is expected to be portrait.
- */
- private void verifyFullscreenMode(
- Runnable runnable, boolean expected, boolean orientationPortrait)
+ private void verifyFullscreenMode(Runnable runnable, boolean orientationPortrait)
throws InterruptedException {
CountDownLatch signal = new CountDownLatch(1);
mInputMethodService.setCountDownLatchForTesting(signal);
@@ -678,12 +379,7 @@ public class InputMethodServiceTest {
}
// Waits for onConfigurationChanged() to finish.
mInstrumentation.waitForIdleSync();
- boolean completed = signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
- if (expected && !completed) {
- fail("Timed out waiting for onConfigurationChanged()");
- } else if (!expected && completed) {
- fail("Unexpected call onConfigurationChanged()");
- }
+ signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
clickOnEditorText();
eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isTrue());
@@ -720,21 +416,7 @@ public class InputMethodServiceTest {
return mTargetPackageName + "/" + INPUT_METHOD_SERVICE_NAME;
}
- /**
- * Sets the value of show_ime_with_hard_keyboard, only if it is different to the default value.
- *
- * @param enabled the value to be set.
- */
- private void setShowImeWithHardKeyboard(boolean enabled) throws IOException {
- if (mShowImeWithHardKeyboardEnabled != enabled) {
- executeShellCommand(enabled
- ? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
- : DISABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD);
- mInstrumentation.waitForIdleSync();
- }
- }
-
- private String executeShellCommand(String cmd) throws IOException {
+ private String executeShellCommand(String cmd) throws Exception {
Log.i(TAG, "Run command: " + cmd);
return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
.executeShellCommand(cmd);
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index 3199e062418f..869497c28def 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -40,6 +40,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.Display;
+import android.view.inputmethod.InputMethodManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -76,9 +77,9 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
public void testPerformShowIme() throws Exception {
synchronized (ImfLock.class) {
mVisibilityApplier.performShowIme(new Binder() /* showInputToken */,
- null /* statsToken */, 0 /* showFlags */, null, SHOW_SOFT_INPUT);
+ null /* statsToken */, InputMethodManager.SHOW_IMPLICIT, null, SHOW_SOFT_INPUT);
}
- verifyShowSoftInput(false, true, 0 /* showFlags */);
+ verifyShowSoftInput(false, true, InputMethodManager.SHOW_IMPLICIT);
}
@Test
@@ -125,7 +126,7 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
@Test
public void testApplyImeVisibility_showImeImplicit() throws Exception {
mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_SHOW_IME_IMPLICIT);
- verifyShowSoftInput(true, true, 0 /* showFlags */);
+ verifyShowSoftInput(true, true, InputMethodManager.SHOW_IMPLICIT);
}
@Test
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
index fae5f86e4007..a38c1626aea1 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
@@ -106,7 +106,7 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
@Test
public void testRequestImeVisibility_showExplicit() {
initImeTargetWindowState(mWindowToken);
- boolean res = mComputer.onImeShowFlags(null, 0 /* showFlags */);
+ boolean res = mComputer.onImeShowFlags(null, 0 /* show explicit */);
mComputer.requestImeVisibility(mWindowToken, res);
final ImeTargetWindowState state = mComputer.getWindowStateOrNull(mWindowToken);
@@ -118,34 +118,6 @@ public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTes
assertThat(mComputer.mRequestedShowExplicitly).isTrue();
}
- /**
- * This checks that the state after an explicit show request does not get reset during
- * a subsequent implicit show request, without an intermediary hide request.
- */
- @Test
- public void testRequestImeVisibility_showExplicit_thenShowImplicit() {
- initImeTargetWindowState(mWindowToken);
- mComputer.onImeShowFlags(null, 0 /* showFlags */);
- assertThat(mComputer.mRequestedShowExplicitly).isTrue();
-
- mComputer.onImeShowFlags(null, InputMethodManager.SHOW_IMPLICIT);
- assertThat(mComputer.mRequestedShowExplicitly).isTrue();
- }
-
- /**
- * This checks that the state after a forced show request does not get reset during
- * a subsequent explicit show request, without an intermediary hide request.
- */
- @Test
- public void testRequestImeVisibility_showForced_thenShowExplicit() {
- initImeTargetWindowState(mWindowToken);
- mComputer.onImeShowFlags(null, InputMethodManager.SHOW_FORCED);
- assertThat(mComputer.mShowForced).isTrue();
-
- mComputer.onImeShowFlags(null, 0 /* showFlags */);
- assertThat(mComputer.mShowForced).isTrue();
- }
-
@Test
public void testRequestImeVisibility_showImplicit_a11yNoImePolicy() {
// Precondition: set AccessibilityService#SHOW_MODE_HIDDEN policy
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
index e87a34ea17d7..42d373b9bf3e 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodBindingControllerTest.java
@@ -19,7 +19,6 @@ package com.android.server.inputmethod;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -163,10 +162,7 @@ public class InputMethodBindingControllerTest extends InputMethodManagerServiceT
assertThat(mBindingController.getCurToken()).isNotNull();
}
// Wait for onServiceConnected()
- boolean completed = mCountDownLatch.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
- if (!completed) {
- fail("Timed out waiting for onServiceConnected()");
- }
+ mCountDownLatch.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
// Verify onServiceConnected() is called and bound successfully.
synchronized (ImfLock.class) {
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp
index e1fd2b34d881..8d0e0c4260e8 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/Android.bp
@@ -43,8 +43,6 @@ android_test_helper_app {
},
export_package_resources: true,
sdk_version: "current",
-
- certificate: "platform",
}
android_library {
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml
index cf7d660a68ef..996322de2c5e 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml
@@ -18,6 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.apps.inputmethod.simpleime">
+ <uses-sdk android:targetSdkVersion="31" />
+
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application android:debuggable="true"
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index 212a243c6a9e..cd3a78ed5e17 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -52,6 +52,7 @@ import android.app.GameModeConfiguration;
import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameModeListener;
+import android.app.IGameStateListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -1578,6 +1579,71 @@ public class GameManagerServiceTests {
assertFalse(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
}
+ @Test
+ public void testAddGameStateListener() throws Exception {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ mockDeviceConfigAll();
+ startUser(gameManagerService, USER_ID_1);
+
+ IGameStateListener mockListener = Mockito.mock(IGameStateListener.class);
+ IBinder binder = Mockito.mock(IBinder.class);
+ when(mockListener.asBinder()).thenReturn(binder);
+ gameManagerService.addGameStateListener(mockListener);
+ verify(binder).linkToDeath(mDeathRecipientCaptor.capture(), anyInt());
+
+ mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO);
+ GameState gameState = new GameState(true, GameState.MODE_NONE);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertFalse(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener, never()).onGameStateChanged(anyString(), any(), anyInt());
+
+ mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_GAME);
+ gameState = new GameState(true, GameState.MODE_NONE);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertTrue(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener).onGameStateChanged(mPackageName, gameState, USER_ID_1);
+ reset(mockListener);
+
+ gameState = new GameState(false, GameState.MODE_CONTENT);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ mTestLooper.dispatchAll();
+ verify(mockListener).onGameStateChanged(mPackageName, gameState, USER_ID_1);
+ reset(mockListener);
+
+ mDeathRecipientCaptor.getValue().binderDied();
+ verify(binder).unlinkToDeath(eq(mDeathRecipientCaptor.getValue()), anyInt());
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertTrue(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener, never()).onGameStateChanged(anyString(), any(), anyInt());
+ }
+
+ @Test
+ public void testRemoveGameStateListener() throws Exception {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ mockDeviceConfigAll();
+ startUser(gameManagerService, USER_ID_1);
+
+ IGameStateListener mockListener = Mockito.mock(IGameStateListener.class);
+ IBinder binder = Mockito.mock(IBinder.class);
+ when(mockListener.asBinder()).thenReturn(binder);
+
+ gameManagerService.addGameStateListener(mockListener);
+ gameManagerService.removeGameStateListener(mockListener);
+ mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_GAME);
+ GameState gameState = new GameState(false, GameState.MODE_CONTENT);
+ gameManagerService.setGameState(mPackageName, gameState, USER_ID_1);
+ assertTrue(gameManagerService.mHandler.hasMessages(SET_GAME_STATE));
+ mTestLooper.dispatchAll();
+ verify(mockListener, never()).onGameStateChanged(anyString(), any(), anyInt());
+ }
+
private List<String> readGameModeInterventionList() throws Exception {
final File interventionFile = new File(InstrumentationRegistry.getContext().getFilesDir(),
"system/game_mode_intervention.list");
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 0530f892a48e..ee3a773580a3 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -34,7 +34,6 @@ android_test {
"services.core",
"services.credentials",
"services.devicepolicy",
- "services.flags",
"services.net",
"services.people",
"services.usage",
diff --git a/services/tests/servicestests/src/com/android/server/flags/FeatureFlagsServiceTest.java b/services/tests/servicestests/src/com/android/server/flags/FeatureFlagsServiceTest.java
deleted file mode 100644
index df4731fb0bb7..000000000000
--- a/services/tests/servicestests/src/com/android/server/flags/FeatureFlagsServiceTest.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.flags.IFeatureFlagsCallback;
-import android.flags.SyncableFlag;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.List;
-
-@Presubmit
-@SmallTest
-public class FeatureFlagsServiceTest {
- private static final String NS = "ns";
- private static final String NAME = "name";
- private static final String PROP_NAME = FlagOverrideStore.getPropName(NS, NAME);
-
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- private FlagOverrideStore mFlagStore;
- @Mock
- private FlagsShellCommand mFlagCommand;
- @Mock
- private IFeatureFlagsCallback mIFeatureFlagsCallback;
- @Mock
- private IBinder mIFeatureFlagsCallbackAsBinder;
- @Mock
- private FeatureFlagsService.PermissionsChecker mPermissionsChecker;
-
- private FeatureFlagsBinder mFeatureFlagsService;
-
- @Before
- public void setup() {
- when(mIFeatureFlagsCallback.asBinder()).thenReturn(mIFeatureFlagsCallbackAsBinder);
- mFeatureFlagsService = new FeatureFlagsBinder(
- mFlagStore, mFlagCommand, mPermissionsChecker);
- }
-
- @Test
- public void testRegisterCallback() {
- mFeatureFlagsService.registerCallback(mIFeatureFlagsCallback);
- try {
- verify(mIFeatureFlagsCallbackAsBinder).linkToDeath(any(), eq(0));
- } catch (RemoteException e) {
- fail("Our mock threw a Remote Exception?");
- }
- }
-
- @Test
- public void testOverrideFlag_requiresWritePermission() {
- SecurityException exc = new SecurityException("not allowed");
- doThrow(exc).when(mPermissionsChecker).assertWritePermission();
-
- SyncableFlag f = new SyncableFlag(NS, "a", "false", false);
-
- try {
- mFeatureFlagsService.overrideFlag(f);
- fail("Should have thrown exception");
- } catch (SecurityException e) {
- assertThat(exc).isEqualTo(e);
- } catch (Exception e) {
- fail("should have thrown a security exception");
- }
- }
-
- @Test
- public void testResetFlag_requiresWritePermission() {
- SecurityException exc = new SecurityException("not allowed");
- doThrow(exc).when(mPermissionsChecker).assertWritePermission();
-
- SyncableFlag f = new SyncableFlag(NS, "a", "false", false);
-
- try {
- mFeatureFlagsService.resetFlag(f);
- fail("Should have thrown exception");
- } catch (SecurityException e) {
- assertThat(exc).isEqualTo(e);
- } catch (Exception e) {
- fail("should have thrown a security exception");
- }
- }
-
- @Test
- public void testSyncFlags_noOverrides() {
- List<SyncableFlag> inputFlags = List.of(
- new SyncableFlag(NS, "a", "false", false),
- new SyncableFlag(NS, "b", "true", false),
- new SyncableFlag(NS, "c", "false", false)
- );
-
- List<SyncableFlag> outputFlags = mFeatureFlagsService.syncFlags(inputFlags);
-
- assertThat(inputFlags.size()).isEqualTo(outputFlags.size());
-
- for (SyncableFlag inpF: inputFlags) {
- boolean found = false;
- for (SyncableFlag outF : outputFlags) {
- if (compareSyncableFlagsNames(inpF, outF)) {
- found = true;
- break;
- }
- }
- assertWithMessage("Failed to find input flag " + inpF + " in the output")
- .that(found).isTrue();
- }
- }
-
- @Test
- public void testSyncFlags_withSomeOverrides() {
- List<SyncableFlag> inputFlags = List.of(
- new SyncableFlag(NS, "a", "false", false),
- new SyncableFlag(NS, "b", "true", false),
- new SyncableFlag(NS, "c", "false", false)
- );
-
- assertThat(mFlagStore).isNotNull();
- when(mFlagStore.get(NS, "c")).thenReturn("true");
- List<SyncableFlag> outputFlags = mFeatureFlagsService.syncFlags(inputFlags);
-
- assertThat(inputFlags.size()).isEqualTo(outputFlags.size());
-
- for (SyncableFlag inpF: inputFlags) {
- boolean found = false;
- for (SyncableFlag outF : outputFlags) {
- if (compareSyncableFlagsNames(inpF, outF)) {
- found = true;
-
- // Once we've found "c", do an extra check
- if (outF.getName().equals("c")) {
- assertWithMessage("Flag " + outF + "was not returned with an override")
- .that(outF.getValue()).isEqualTo("true");
- }
- break;
- }
- }
- assertWithMessage("Failed to find input flag " + inpF + " in the output")
- .that(found).isTrue();
- }
- }
-
- @Test
- public void testSyncFlags_twoCallsWithDifferentDefaults() {
- List<SyncableFlag> inputFlagsFirst = List.of(
- new SyncableFlag(NS, "a", "false", false)
- );
- List<SyncableFlag> inputFlagsSecond = List.of(
- new SyncableFlag(NS, "a", "true", false),
- new SyncableFlag(NS, "b", "false", false)
- );
-
- List<SyncableFlag> outputFlagsFirst = mFeatureFlagsService.syncFlags(inputFlagsFirst);
- List<SyncableFlag> outputFlagsSecond = mFeatureFlagsService.syncFlags(inputFlagsSecond);
-
- assertThat(inputFlagsFirst.size()).isEqualTo(outputFlagsFirst.size());
- assertThat(inputFlagsSecond.size()).isEqualTo(outputFlagsSecond.size());
-
- // This test only cares that the "a" flag passed in the second time came out with the
- // same value that was passed in the first time.
-
- boolean found = false;
- for (SyncableFlag second : outputFlagsSecond) {
- if (compareSyncableFlagsNames(second, inputFlagsFirst.get(0))) {
- found = true;
- assertThat(second.getValue()).isEqualTo(inputFlagsFirst.get(0).getValue());
- break;
- }
- }
-
- assertWithMessage(
- "Failed to find flag " + inputFlagsFirst.get(0) + " in the second calls output")
- .that(found).isTrue();
- }
-
- @Test
- public void testQueryFlags_onlyOnce() {
- List<SyncableFlag> inputFlags = List.of(
- new SyncableFlag(NS, "a", "false", false),
- new SyncableFlag(NS, "b", "true", false),
- new SyncableFlag(NS, "c", "false", false)
- );
-
- List<SyncableFlag> outputFlags = mFeatureFlagsService.queryFlags(inputFlags);
-
- assertThat(inputFlags.size()).isEqualTo(outputFlags.size());
-
- for (SyncableFlag inpF: inputFlags) {
- boolean found = false;
- for (SyncableFlag outF : outputFlags) {
- if (compareSyncableFlagsNames(inpF, outF)) {
- found = true;
- break;
- }
- }
- assertWithMessage("Failed to find input flag " + inpF + " in the output")
- .that(found).isTrue();
- }
- }
-
- @Test
- public void testQueryFlags_twoCallsWithDifferentDefaults() {
- List<SyncableFlag> inputFlagsFirst = List.of(
- new SyncableFlag(NS, "a", "false", false)
- );
- List<SyncableFlag> inputFlagsSecond = List.of(
- new SyncableFlag(NS, "a", "true", false),
- new SyncableFlag(NS, "b", "false", false)
- );
-
- List<SyncableFlag> outputFlagsFirst = mFeatureFlagsService.queryFlags(inputFlagsFirst);
- List<SyncableFlag> outputFlagsSecond = mFeatureFlagsService.queryFlags(inputFlagsSecond);
-
- assertThat(inputFlagsFirst.size()).isEqualTo(outputFlagsFirst.size());
- assertThat(inputFlagsSecond.size()).isEqualTo(outputFlagsSecond.size());
-
- // This test only cares that the "a" flag passed in the second time came out with the
- // same value that was passed in (i.e. it wasn't cached).
-
- boolean found = false;
- for (SyncableFlag second : outputFlagsSecond) {
- if (compareSyncableFlagsNames(second, inputFlagsSecond.get(0))) {
- found = true;
- assertThat(second.getValue()).isEqualTo(inputFlagsSecond.get(0).getValue());
- break;
- }
- }
-
- assertWithMessage(
- "Failed to find flag " + inputFlagsSecond.get(0) + " in the second calls output")
- .that(found).isTrue();
- }
-
- @Test
- public void testOverrideFlag() {
- SyncableFlag f = new SyncableFlag(NS, "a", "false", false);
-
- mFeatureFlagsService.overrideFlag(f);
-
- verify(mFlagStore).set(f.getNamespace(), f.getName(), f.getValue());
- }
-
- @Test
- public void testResetFlag() {
- SyncableFlag f = new SyncableFlag(NS, "a", "false", false);
-
- mFeatureFlagsService.resetFlag(f);
-
- verify(mFlagStore).erase(f.getNamespace(), f.getName());
- }
-
-
- private static boolean compareSyncableFlagsNames(SyncableFlag a, SyncableFlag b) {
- return a.getNamespace().equals(b.getNamespace())
- && a.getName().equals(b.getName())
- && a.isDynamic() == b.isDynamic();
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/flags/FlagCacheTest.java b/services/tests/servicestests/src/com/android/server/flags/FlagCacheTest.java
deleted file mode 100644
index c2cf540d1d62..000000000000
--- a/services/tests/servicestests/src/com/android/server/flags/FlagCacheTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class FlagCacheTest {
- private static final String NS = "ns";
- private static final String NAME = "name";
-
- FlagCache mFlagCache = new FlagCache();
-
- @Test
- public void testGetOrNull_unset() {
- assertThat(mFlagCache.getOrNull(NS, NAME)).isNull();
- }
-
- @Test
- public void testGetOrSet_unset() {
- assertThat(mFlagCache.getOrSet(NS, NAME, "value")).isEqualTo("value");
- }
-
- @Test
- public void testGetOrSet_alreadySet() {
- mFlagCache.setIfChanged(NS, NAME, "value");
- assertThat(mFlagCache.getOrSet(NS, NAME, "newvalue")).isEqualTo("value");
- }
-
- @Test
- public void testSetIfChanged_unset() {
- assertThat(mFlagCache.setIfChanged(NS, NAME, "value")).isTrue();
- }
-
- @Test
- public void testSetIfChanged_noChange() {
- mFlagCache.setIfChanged(NS, NAME, "value");
- assertThat(mFlagCache.setIfChanged(NS, NAME, "value")).isFalse();
- }
-
- @Test
- public void testSetIfChanged_changing() {
- mFlagCache.setIfChanged(NS, NAME, "value");
- assertThat(mFlagCache.setIfChanged(NS, NAME, "newvalue")).isTrue();
- }
-
- @Test
- public void testContainsNamespace_unset() {
- assertThat(mFlagCache.containsNamespace(NS)).isFalse();
- }
-
- @Test
- public void testContainsNamespace_set() {
- mFlagCache.setIfChanged(NS, NAME, "value");
- assertThat(mFlagCache.containsNamespace(NS)).isTrue();
- }
-
- @Test
- public void testContains_unset() {
- assertThat(mFlagCache.contains(NS, NAME)).isFalse();
- }
-
- @Test
- public void testContains_set() {
- mFlagCache.setIfChanged(NS, NAME, "value");
- assertThat(mFlagCache.contains(NS, NAME)).isTrue();
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/flags/FlagOverrideStoreTest.java b/services/tests/servicestests/src/com/android/server/flags/FlagOverrideStoreTest.java
deleted file mode 100644
index 6cc3acfb6125..000000000000
--- a/services/tests/servicestests/src/com/android/server/flags/FlagOverrideStoreTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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 com.android.server.flags;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@Presubmit
-@SmallTest
-public class FlagOverrideStoreTest {
- private static final String NS = "ns";
- private static final String NAME = "name";
- private static final String PROP_NAME = FlagOverrideStore.getPropName(NS, NAME);
-
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- private SettingsProxy mSettingsProxy;
- @Mock
- private FlagOverrideStore.FlagChangeCallback mCallback;
-
- private FlagOverrideStore mFlagStore;
-
- @Before
- public void setup() {
- mFlagStore = new FlagOverrideStore(mSettingsProxy);
- mFlagStore.setChangeCallback(mCallback);
- }
-
- @Test
- public void testSet_unset() {
- mFlagStore.set(NS, NAME, "value");
- verify(mSettingsProxy).putString(PROP_NAME, "value");
- }
-
- @Test
- public void testSet_setTwice() {
- mFlagStore.set(NS, NAME, "value");
- mFlagStore.set(NS, NAME, "newvalue");
- verify(mSettingsProxy).putString(PROP_NAME, "value");
- verify(mSettingsProxy).putString(PROP_NAME, "newvalue");
- }
-
- @Test
- public void testGet_unset() {
- assertThat(mFlagStore.get(NS, NAME)).isNull();
- }
-
- @Test
- public void testGet_set() {
- when(mSettingsProxy.getString(PROP_NAME)).thenReturn("value");
- assertThat(mFlagStore.get(NS, NAME)).isEqualTo("value");
- }
-
- @Test
- public void testErase() {
- mFlagStore.erase(NS, NAME);
- verify(mSettingsProxy).putString(PROP_NAME, null);
- }
-
- @Test
- public void testContains_unset() {
- assertThat(mFlagStore.contains(NS, NAME)).isFalse();
- }
-
- @Test
- public void testContains_set() {
- when(mSettingsProxy.getString(PROP_NAME)).thenReturn("value");
- assertThat(mFlagStore.contains(NS, NAME)).isTrue();
- }
-
- @Test
- public void testCallback_onSet() {
- mFlagStore.set(NS, NAME, "value");
- verify(mCallback).onFlagChanged(NS, NAME, "value");
- }
-
- @Test
- public void testCallback_onErase() {
- mFlagStore.erase(NS, NAME);
- verify(mCallback).onFlagChanged(NS, NAME, null);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/flags/OWNERS b/services/tests/servicestests/src/com/android/server/flags/OWNERS
deleted file mode 100644
index 7ed369e37106..000000000000
--- a/services/tests/servicestests/src/com/android/server/flags/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /services/flags/OWNERS