summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/SystemServiceRegistry.java7
-rw-r--r--core/java/android/view/textservice/SpellCheckerSession.java13
-rw-r--r--core/java/android/view/textservice/TextServicesManager.java56
-rw-r--r--core/java/com/android/internal/textservice/ITextServicesManager.aidl13
-rw-r--r--services/core/java/com/android/server/textservices/TextServicesManagerService.java41
5 files changed, 88 insertions, 42 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 3adafd725a10..2dc225af6482 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -439,10 +439,11 @@ final class SystemServiceRegistry {
}});
registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class,
- new StaticServiceFetcher<TextServicesManager>() {
+ new CachedServiceFetcher<TextServicesManager>() {
@Override
- public TextServicesManager createService() {
- return TextServicesManager.getInstance();
+ public TextServicesManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ return TextServicesManager.createInstance(ctx);
}});
registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class,
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 9733701ee0f0..f553ca512881 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -27,7 +27,6 @@ import android.util.Log;
import com.android.internal.textservice.ISpellCheckerSession;
import com.android.internal.textservice.ISpellCheckerSessionListener;
-import com.android.internal.textservice.ITextServicesManager;
import com.android.internal.textservice.ITextServicesSessionListener;
import dalvik.system.CloseGuard;
@@ -96,7 +95,7 @@ public class SpellCheckerSession {
private static final int MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE = 2;
private final InternalListener mInternalListener;
- private final ITextServicesManager mTextServicesManager;
+ private final TextServicesManager mTextServicesManager;
private final SpellCheckerInfo mSpellCheckerInfo;
@UnsupportedAppUsage
private final SpellCheckerSessionListener mSpellCheckerSessionListener;
@@ -124,7 +123,7 @@ public class SpellCheckerSession {
* @hide
*/
public SpellCheckerSession(
- SpellCheckerInfo info, ITextServicesManager tsm, SpellCheckerSessionListener listener) {
+ SpellCheckerInfo info, TextServicesManager tsm, SpellCheckerSessionListener listener) {
if (info == null || listener == null || tsm == null) {
throw new NullPointerException();
}
@@ -166,12 +165,8 @@ public class SpellCheckerSession {
*/
public void close() {
mGuard.close();
- try {
- mSpellCheckerSessionListenerImpl.close();
- mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl);
- } catch (RemoteException e) {
- // do nothing
- }
+ mSpellCheckerSessionListenerImpl.close();
+ mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl);
}
/**
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 5dc8b19444b0..9ff64d9b268a 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -16,16 +16,20 @@
package android.view.textservice;
+import android.annotation.NonNull;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
+import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
+import android.os.UserHandle;
import android.util.Log;
import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
import com.android.internal.textservice.ITextServicesManager;
import java.util.Locale;
@@ -67,17 +71,41 @@ public final class TextServicesManager {
private static final String TAG = TextServicesManager.class.getSimpleName();
private static final boolean DBG = false;
+ /**
+ * @deprecated Do not use. Just kept because of {@link UnsupportedAppUsage} in
+ * {@link #getInstance()}.
+ */
+ @Deprecated
private static TextServicesManager sInstance;
private final ITextServicesManager mService;
- private TextServicesManager() throws ServiceNotFoundException {
+ @UserIdInt
+ private final int mUserId;
+
+ private TextServicesManager(@UserIdInt int userId) throws ServiceNotFoundException {
mService = ITextServicesManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TEXT_SERVICES_MANAGER_SERVICE));
+ mUserId = userId;
+ }
+
+ /**
+ * The factory method of {@link TextServicesManager}.
+ *
+ * @param context {@link Context} from which {@link TextServicesManager} should be instantiated.
+ * @return {@link TextServicesManager} that is associated with {@link Context#getUserId()}.
+ * @throws ServiceNotFoundException When {@link TextServicesManager} is not available.
+ * @hide
+ */
+ @NonNull
+ public static TextServicesManager createInstance(@NonNull Context context)
+ throws ServiceNotFoundException {
+ return new TextServicesManager(context.getUserId());
}
/**
- * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist.
+ * @deprecated Do not use. Just kept because of {@link UnsupportedAppUsage} in
+ * {@link #getInstance()}.
* @hide
*/
@UnsupportedAppUsage
@@ -85,7 +113,7 @@ public final class TextServicesManager {
synchronized (TextServicesManager.class) {
if (sInstance == null) {
try {
- sInstance = new TextServicesManager();
+ sInstance = new TextServicesManager(UserHandle.myUserId());
} catch (ServiceNotFoundException e) {
throw new IllegalStateException(e);
}
@@ -136,7 +164,7 @@ public final class TextServicesManager {
final SpellCheckerInfo sci;
try {
- sci = mService.getCurrentSpellChecker(null);
+ sci = mService.getCurrentSpellChecker(mUserId, null);
} catch (RemoteException e) {
return null;
}
@@ -174,9 +202,9 @@ public final class TextServicesManager {
if (subtypeInUse == null) {
return null;
}
- final SpellCheckerSession session = new SpellCheckerSession(sci, mService, listener);
+ final SpellCheckerSession session = new SpellCheckerSession(sci, this, listener);
try {
- mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
+ mService.getSpellCheckerService(mUserId, sci.getId(), subtypeInUse.getLocale(),
session.getTextServicesSessionListener(),
session.getSpellCheckerSessionListener(), bundle);
} catch (RemoteException e) {
@@ -191,7 +219,7 @@ public final class TextServicesManager {
@UnsupportedAppUsage
public SpellCheckerInfo[] getEnabledSpellCheckers() {
try {
- final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers();
+ final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers(mUserId);
if (DBG) {
Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null"));
}
@@ -208,7 +236,7 @@ public final class TextServicesManager {
public SpellCheckerInfo getCurrentSpellChecker() {
try {
// Passing null as a locale for ICS
- return mService.getCurrentSpellChecker(null);
+ return mService.getCurrentSpellChecker(mUserId, null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -221,7 +249,7 @@ public final class TextServicesManager {
public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
boolean allowImplicitlySelectedSubtype) {
try {
- return mService.getCurrentSpellCheckerSubtype(allowImplicitlySelectedSubtype);
+ return mService.getCurrentSpellCheckerSubtype(mUserId, allowImplicitlySelectedSubtype);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -233,7 +261,15 @@ public final class TextServicesManager {
@UnsupportedAppUsage
public boolean isSpellCheckerEnabled() {
try {
- return mService.isSpellCheckerEnabled();
+ return mService.isSpellCheckerEnabled(mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
+ try {
+ mService.finishSpellCheckerService(mUserId, listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index 20f2aa06cf1e..8022949d1728 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -29,12 +29,13 @@ import android.view.textservice.SpellCheckerSubtype;
* @hide
*/
interface ITextServicesManager {
- SpellCheckerInfo getCurrentSpellChecker(String locale);
- SpellCheckerSubtype getCurrentSpellCheckerSubtype(boolean allowImplicitlySelectedSubtype);
- oneway void getSpellCheckerService(String sciId, in String locale,
+ SpellCheckerInfo getCurrentSpellChecker(int userId, String locale);
+ SpellCheckerSubtype getCurrentSpellCheckerSubtype(int userId,
+ boolean allowImplicitlySelectedSubtype);
+ oneway void getSpellCheckerService(int userId, String sciId, in String locale,
in ITextServicesSessionListener tsListener,
in ISpellCheckerSessionListener scListener, in Bundle bundle);
- oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
- boolean isSpellCheckerEnabled();
- SpellCheckerInfo[] getEnabledSpellCheckers();
+ oneway void finishSpellCheckerService(int userId, in ISpellCheckerSessionListener listener);
+ boolean isSpellCheckerEnabled(int userId);
+ SpellCheckerInfo[] getEnabledSpellCheckers(int userId);
}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index 7236d79c55ab..d4aa59d3ce85 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.textservices;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -513,8 +515,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
// TODO: Save SpellCheckerService by supported languages. Currently only one spell
// checker is saved.
@Override
- public SpellCheckerInfo getCurrentSpellChecker(String locale) {
- int userId = UserHandle.getCallingUserId();
+ public SpellCheckerInfo getCurrentSpellChecker(@UserIdInt int userId, String locale) {
+ verifyUser(userId);
synchronized (mLock) {
final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
if (tsd == null) return null;
@@ -527,11 +529,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
// TODO: Save SpellCheckerSubtype by supported languages by looking at "locale".
@Override
public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
- boolean allowImplicitlySelectedSubtype) {
+ @UserIdInt int userId, boolean allowImplicitlySelectedSubtype) {
+ verifyUser(userId);
+
final int subtypeHashCode;
final SpellCheckerInfo sci;
final Locale systemLocale;
- final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
@@ -591,17 +594,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
@Override
- public void getSpellCheckerService(String sciId, String locale,
+ public void getSpellCheckerService(@UserIdInt int userId, String sciId, String locale,
ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
Bundle bundle) {
+ verifyUser(userId);
if (TextUtils.isEmpty(sciId) || tsListener == null || scListener == null) {
Slog.e(TAG, "getSpellCheckerService: Invalid input.");
return;
}
- int callingUserId = UserHandle.getCallingUserId();
synchronized (mLock) {
- final TextServicesData tsd = getDataFromCallingUserIdLocked(callingUserId);
+ final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
if (tsd == null) return;
HashMap<String, SpellCheckerInfo> spellCheckerMap = tsd.mSpellCheckerMap;
@@ -634,8 +637,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
@Override
- public boolean isSpellCheckerEnabled() {
- int userId = UserHandle.getCallingUserId();
+ public boolean isSpellCheckerEnabled(@UserIdInt int userId) {
+ verifyUser(userId);
synchronized (mLock) {
final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
@@ -671,11 +674,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
@Override
- public SpellCheckerInfo[] getEnabledSpellCheckers() {
- int callingUserId = UserHandle.getCallingUserId();
+ public SpellCheckerInfo[] getEnabledSpellCheckers(@UserIdInt int userId) {
+ verifyUser(userId);
synchronized (mLock) {
- final TextServicesData tsd = getDataFromCallingUserIdLocked(callingUserId);
+ final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
if (tsd == null) return null;
ArrayList<SpellCheckerInfo> spellCheckerList = tsd.mSpellCheckerList;
@@ -691,11 +694,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
@Override
- public void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
+ public void finishSpellCheckerService(@UserIdInt int userId,
+ ISpellCheckerSessionListener listener) {
if (DBG) {
Slog.d(TAG, "FinishSpellCheckerService");
}
- int userId = UserHandle.getCallingUserId();
+ verifyUser(userId);
synchronized (mLock) {
final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
@@ -716,6 +720,15 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
}
+ private void verifyUser(@UserIdInt int userId) {
+ final int callingUserId = UserHandle.getCallingUserId();
+ if (userId != callingUserId) {
+ mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL,
+ "Cross-user interaction requires INTERACT_ACROSS_USERS_FULL. userId=" + userId
+ + " callingUserId=" + callingUserId);
+ }
+ }
+
private void setCurrentSpellCheckerLocked(@Nullable SpellCheckerInfo sci, TextServicesData tsd) {
final String sciId = (sci != null) ? sci.getId() : "";
if (DBG) {