Merge "Remove PER_PROFILE_IME_ENABLED property"
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2ee6b7d..5308cd3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -90,7 +90,6 @@
 import android.util.Log;
 import android.util.MemoryIntArray;
 import android.view.Display;
-import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.widget.ILockSettings;
@@ -9298,13 +9297,6 @@
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
             CLONE_TO_MANAGED_PROFILE.add(SHOW_IME_WITH_HARD_KEYBOARD);
-            if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-                CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
-                CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
-                CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
-                CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER);
-                CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER_SUBTYPE);
-            }
         }
 
         /** @hide */
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
index 05143a1..0689806 100644
--- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java
+++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
@@ -43,17 +43,6 @@
      */
     private static final String PROP_DEBUG_MULTI_CLIENT_IME = "persist.debug.multi_client_ime";
 
-    /**
-     * System property key for debugging purpose. The value must be empty, "1", or "0".
-     *
-     * <p>Values 'y', 'yes', '1', 'true' or 'on' are considered true.</p>
-     *
-     * <p>To set, run "adb root && adb shell setprop persist.debug.per_profile_ime 1".</p>
-     *
-     * <p>This value will be ignored when {@link Build#IS_DEBUGGABLE} returns {@code false}.</p>
-     */
-    private static final String PROP_DEBUG_PER_PROFILE_IME = "persist.debug.per_profile_ime";
-
     @Nullable
     private static ComponentName getMultiClientImeComponentName() {
         if (Build.IS_DEBUGGABLE) {
@@ -91,19 +80,4 @@
      */
     @TestApi
     public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
-
-    /**
-     * {@code true} when per-profile IME is enabled.
-     * @hide
-     */
-    public static final boolean PER_PROFILE_IME_ENABLED;
-    static {
-        if (MULTI_CLIENT_IME_ENABLED) {
-            PER_PROFILE_IME_ENABLED = true;
-        } else if (Build.IS_DEBUGGABLE) {
-            PER_PROFILE_IME_ENABLED = SystemProperties.getBoolean(PROP_DEBUG_PER_PROFILE_IME, true);
-        } else {
-            PER_PROFILE_IME_ENABLED = true;
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 49b42df..09e9375 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -17,7 +17,6 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
-import static android.view.inputmethod.InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -1036,9 +1035,7 @@
                 // sender userId can be a real user ID or USER_ALL.
                 final int senderUserId = pendingResult.getSendingUserId();
                 if (senderUserId != UserHandle.USER_ALL) {
-                    final int resolvedUserId = PER_PROFILE_IME_ENABLED
-                            ? senderUserId : mUserManagerInternal.getProfileParentId(senderUserId);
-                    if (resolvedUserId != mSettings.getCurrentUserId()) {
+                    if (senderUserId != mSettings.getCurrentUserId()) {
                         // A background user is trying to hide the dialog. Ignore.
                         return;
                     }
@@ -1662,9 +1659,6 @@
         if (userId == mSettings.getCurrentUserId()) {
             return true;
         }
-        if (!PER_PROFILE_IME_ENABLED && mSettings.isCurrentProfile(userId)) {
-            return true;
-        }
 
         // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
         // foreground user, not for the user of that process. Accordingly InputMethodManagerService
@@ -3005,7 +2999,7 @@
             return InputBindResult.INVALID_USER;
         }
 
-        if (PER_PROFILE_IME_ENABLED && userId != mSettings.getCurrentUserId()) {
+        if (userId != mSettings.getCurrentUserId()) {
             switchUserLocked(userId);
         }
         // Master feature flag that overrides other conditions and forces IME preRendering.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index b5e19ae..77e2fbd 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -35,13 +35,11 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.IntArray;
 import android.util.Pair;
 import android.util.Printer;
 import android.util.Slog;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
-import android.view.inputmethod.InputMethodSystemProperty;
 import android.view.textservice.SpellCheckerInfo;
 
 import com.android.internal.annotations.GuardedBy;
@@ -1303,9 +1301,6 @@
      * Converts a user ID, which can be a pseudo user ID such as {@link UserHandle#USER_ALL} to a
      * list of real user IDs.
      *
-     * <p>This method also converts profile user ID to profile parent user ID unless
-     * {@link InputMethodSystemProperty#PER_PROFILE_IME_ENABLED} is {@code true}.</p>
-     *
      * @param userIdToBeResolved A user ID. Two pseudo user ID {@link UserHandle#USER_CURRENT} and
      *                           {@link UserHandle#USER_ALL} are also supported
      * @param currentUserId A real user ID, which will be used when {@link UserHandle#USER_CURRENT}
@@ -1320,17 +1315,7 @@
                 LocalServices.getService(UserManagerInternal.class);
 
         if (userIdToBeResolved == UserHandle.USER_ALL) {
-            if (InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-                return userManagerInternal.getUserIds();
-            }
-            final IntArray result = new IntArray();
-            for (int userId : userManagerInternal.getUserIds()) {
-                final int parentUserId = userManagerInternal.getProfileParentId(userId);
-                if (result.indexOf(parentUserId) < 0) {
-                    result.add(parentUserId);
-                }
-            }
-            return result.toArray();
+            return userManagerInternal.getUserIds();
         }
 
         final int sourceUserId;
@@ -1353,8 +1338,6 @@
             }
             return new int[]{};
         }
-        final int resolvedUserId = InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                ? sourceUserId : userManagerInternal.getProfileParentId(sourceUserId);
-        return new int[]{resolvedUserId};
+        return new int[]{sourceUserId};
     }
 }
diff --git a/services/core/java/com/android/server/textservices/LazyIntToIntMap.java b/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
deleted file mode 100644
index 2e7f2a9..0000000
--- a/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
+++ /dev/null
@@ -1,64 +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.server.textservices;
-
-import android.annotation.NonNull;
-import android.util.SparseIntArray;
-
-import java.util.function.IntUnaryOperator;
-
-/**
- * Simple int-to-int key-value-store that is to be lazily initialized with the given
- * {@link IntUnaryOperator}.
- */
-final class LazyIntToIntMap {
-
-    private final SparseIntArray mMap = new SparseIntArray();
-
-    @NonNull
-    private final IntUnaryOperator mMappingFunction;
-
-    /**
-     * @param mappingFunction int to int mapping rules to be (lazily) evaluated
-     */
-    public LazyIntToIntMap(@NonNull IntUnaryOperator mappingFunction) {
-        mMappingFunction = mappingFunction;
-    }
-
-    /**
-     * Deletes {@code key} and associated value.
-     * @param key key to be deleted
-     */
-    public void delete(int key) {
-        mMap.delete(key);
-    }
-
-    /**
-     * @param key key associated with the value
-     * @return value associated with the {@code key}. If this is the first time to access
-     * {@code key}, then {@code mappingFunction} passed to the constructor will be evaluated
-     */
-    public int get(int key) {
-        final int index = mMap.indexOfKey(key);
-        if (index >= 0) {
-            return mMap.valueAt(index);
-        }
-        final int value = mMappingFunction.applyAsInt(key);
-        mMap.append(key, value);
-        return value;
-    }
-}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index d4aa59d..e0bac93 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -43,7 +43,6 @@
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.inputmethod.InputMethodSystemProperty;
 import android.view.textservice.SpellCheckerInfo;
 import android.view.textservice.SpellCheckerSubtype;
 
@@ -86,10 +85,6 @@
     private final UserManager mUserManager;
     private final Object mLock = new Object();
 
-    @NonNull
-    @GuardedBy("mLock")
-    private final LazyIntToIntMap mSpellCheckerOwnerUserIdMap;
-
     private static class TextServicesData {
         @UserIdInt
         private final int mUserId;
@@ -312,9 +307,6 @@
 
     void onStopUser(@UserIdInt int userId) {
         synchronized (mLock) {
-            // Clear user ID mapping table.
-            mSpellCheckerOwnerUserIdMap.delete(userId);
-
             // Clean per-user data
             TextServicesData tsd = mUserData.get(userId);
             if (tsd == null) return;
@@ -334,33 +326,12 @@
     public TextServicesManagerService(Context context) {
         mContext = context;
         mUserManager = mContext.getSystemService(UserManager.class);
-        mSpellCheckerOwnerUserIdMap = new LazyIntToIntMap(callingUserId -> {
-            if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    final UserInfo parent = mUserManager.getProfileParent(callingUserId);
-                    return (parent != null) ? parent.id : callingUserId;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            } else {
-                return callingUserId;
-            }
-        });
-
         mMonitor = new TextServicesMonitor();
         mMonitor.register(context, null, UserHandle.ALL, true);
     }
 
     @GuardedBy("mLock")
     private void initializeInternalStateLocked(@UserIdInt int userId) {
-        // When DISABLE_PER_PROFILE_SPELL_CHECKER is true, we make sure here that work profile users
-        // will never have non-null TextServicesData for their user ID.
-        if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                && userId != mSpellCheckerOwnerUserIdMap.get(userId)) {
-            return;
-        }
-
         TextServicesData tsd = mUserData.get(userId);
         if (tsd == null) {
             tsd = new TextServicesData(userId, mContext);
@@ -506,8 +477,7 @@
     @Nullable
     private SpellCheckerInfo getCurrentSpellCheckerForUser(@UserIdInt int userId) {
         synchronized (mLock) {
-            final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(userId);
-            final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
+            final TextServicesData data = mUserData.get(userId);
             return data != null ? data.getCurrentSpellChecker() : null;
         }
     }
@@ -790,27 +760,7 @@
     @GuardedBy("mLock")
     @Nullable
     private TextServicesData getDataFromCallingUserIdLocked(@UserIdInt int callingUserId) {
-        final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(callingUserId);
-        final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
-        if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-            if (spellCheckerOwnerUserId != callingUserId) {
-                // Calling process is running under child profile.
-                if (data == null) {
-                    return null;
-                }
-                final SpellCheckerInfo info = data.getCurrentSpellChecker();
-                if (info == null) {
-                    return null;
-                }
-                final ServiceInfo serviceInfo = info.getServiceInfo();
-                if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    // To be conservative, non pre-installed spell checker services are not allowed
-                    // to be used for child profiles.
-                    return null;
-                }
-            }
-        }
-        return data;
+        return mUserData.get(callingUserId);
     }
 
     private static final class SessionRequest {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 48921ea..de8612a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -228,7 +228,6 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -9403,12 +9402,6 @@
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-
-        // TODO When InputMethodManager supports per user calls remove this restriction.
-        if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                && !checkCallerIsCurrentUserOrProfile()) {
-            return false;
-        }
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         if (packageList != null) {
             List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
@@ -9464,26 +9457,16 @@
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             List<String> result = null;
-            // If we have multiple profiles we return the intersection of the
-            // permitted lists. This can happen in cases where we have a device
-            // and profile owner.
-            int[] profileIds = InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                    ? new int[]{callingUserId}
-                    : mUserManager.getProfileIdsWithDisabled(callingUserId);
-            for (int profileId : profileIds) {
-                // Just loop though all admins, only device or profiles
-                // owners can have permitted lists set.
-                DevicePolicyData policy = getUserDataUnchecked(profileId);
-                final int N = policy.mAdminList.size();
-                for (int j = 0; j < N; j++) {
-                    ActiveAdmin admin = policy.mAdminList.get(j);
-                    List<String> fromAdmin = admin.permittedInputMethods;
-                    if (fromAdmin != null) {
-                        if (result == null) {
-                            result = new ArrayList<String>(fromAdmin);
-                        } else {
-                            result.retainAll(fromAdmin);
-                        }
+            // Only device or profile owners can have permitted lists set.
+            DevicePolicyData policy = getUserDataUnchecked(callingUserId);
+            for (int i = 0; i < policy.mAdminList.size(); i++) {
+                ActiveAdmin admin = policy.mAdminList.get(i);
+                List<String> fromAdmin = admin.permittedInputMethods;
+                if (fromAdmin != null) {
+                    if (result == null) {
+                        result = new ArrayList<String>(fromAdmin);
+                    } else {
+                        result.retainAll(fromAdmin);
                     }
                 }
             }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 699bec2..261a83c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -33,7 +33,6 @@
 import android.content.pm.ResolveInfo;
 import android.util.ArraySet;
 import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -61,17 +60,11 @@
 
     @VisibleForTesting
     interface Injector {
-        boolean isPerProfileImeEnabled();
         @NonNull
         List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
     }
 
     private static final class DefaultInjector implements Injector {
-        @Override
-        public boolean isPerProfileImeEnabled() {
-            return InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
-        }
-
         @NonNull
         @Override
         public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
@@ -108,13 +101,7 @@
         // Newly installed system apps are uninstalled when they are not required and are either
         // disallowed or have a launcher icon.
         nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName()));
-        if (mInjector.isPerProfileImeEnabled()) {
-            nonRequiredApps.removeAll(getSystemInputMethods(userId));
-        } else if (ACTION_PROVISION_MANAGED_DEVICE.equals(provisioningAction)
-                || ACTION_PROVISION_MANAGED_USER.equals(provisioningAction)) {
-            // Don't delete the system input method packages in case of Device owner provisioning.
-            nonRequiredApps.removeAll(getSystemInputMethods(userId));
-        }
+        nonRequiredApps.removeAll(getSystemInputMethods(userId));
         nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
         return nonRequiredApps;
     }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index 757a046..a3cc915 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -79,7 +79,6 @@
                 InstrumentationRegistry.getTargetContext().getCacheDir());
 
         setSystemInputMethods();
-        setIsPerProfileModeEnabled(false);
         setRequiredAppsManagedDevice();
         setVendorRequiredAppsManagedDevice();
         setDisallowedAppsManagedDevice();
@@ -164,15 +163,6 @@
     }
 
     @Test
-    public void testProfileOwnerImesAreRequiredForPerProfileImeMode() {
-        setSystemAppsWithLauncher("app.a", "app.b");
-        setSystemInputMethods("app.a");
-        setIsPerProfileModeEnabled(true);
-
-        verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.b");
-    }
-
-    @Test
     public void testManagedUserImesAreRequired() {
         setSystemAppsWithLauncher("app.a", "app.b");
         setSystemInputMethods("app.a");
@@ -344,10 +334,6 @@
         when(mInjector.getInputMethodListAsUser(eq(TEST_USER_ID))).thenReturn(inputMethods);
     }
 
-    private void setIsPerProfileModeEnabled(boolean enabled) {
-        when(mInjector.isPerProfileImeEnabled()).thenReturn(enabled);
-    }
-
     private void setSystemAppsWithLauncher(String... apps) {
         mSystemAppsWithLauncher = apps;
     }
diff --git a/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java b/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
deleted file mode 100644
index f80afb2..0000000
--- a/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
+++ /dev/null
@@ -1,92 +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.server.textservices;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.IntUnaryOperator;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class LazyIntToIntMapTest {
-    @Test
-    public void testLaziness() {
-        final IntUnaryOperator func = mock(IntUnaryOperator.class);
-        when(func.applyAsInt(eq(1))).thenReturn(11);
-        when(func.applyAsInt(eq(2))).thenReturn(22);
-
-        final LazyIntToIntMap map = new LazyIntToIntMap(func);
-
-        verify(func, never()).applyAsInt(anyInt());
-
-        assertEquals(22, map.get(2));
-        verify(func, times(0)).applyAsInt(eq(1));
-        verify(func, times(1)).applyAsInt(eq(2));
-
-        // Accessing to the same key does not evaluate the function again.
-        assertEquals(22, map.get(2));
-        verify(func, times(0)).applyAsInt(eq(1));
-        verify(func, times(1)).applyAsInt(eq(2));
-    }
-
-    @Test
-    public void testDelete() {
-        final IntUnaryOperator func1 = mock(IntUnaryOperator.class);
-        when(func1.applyAsInt(eq(1))).thenReturn(11);
-        when(func1.applyAsInt(eq(2))).thenReturn(22);
-
-        final IntUnaryOperator func2 = mock(IntUnaryOperator.class);
-        when(func2.applyAsInt(eq(1))).thenReturn(111);
-        when(func2.applyAsInt(eq(2))).thenReturn(222);
-
-        final AtomicReference<IntUnaryOperator> funcRef = new AtomicReference<>(func1);
-        final LazyIntToIntMap map = new LazyIntToIntMap(i -> funcRef.get().applyAsInt(i));
-
-        verify(func1, never()).applyAsInt(anyInt());
-        verify(func2, never()).applyAsInt(anyInt());
-
-        assertEquals(22, map.get(2));
-        verify(func1, times(1)).applyAsInt(eq(2));
-        verify(func2, times(0)).applyAsInt(eq(2));
-
-        // Swap func1 with func2 then invalidate the key=2
-        funcRef.set(func2);
-        map.delete(2);
-
-        // Calling get(2) again should re-evaluate the value.
-        assertEquals(222, map.get(2));
-        verify(func1, times(1)).applyAsInt(eq(2));
-        verify(func2, times(1)).applyAsInt(eq(2));
-
-        // Trying to delete non-existing keys does nothing.
-        map.delete(1);
-    }
-}