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);
- }
-}