diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java index 98c2d7fdd55f5..357c3332fe105 100644 --- a/media/java/android/media/AudioManagerInternal.java +++ b/media/java/android/media/AudioManagerInternal.java @@ -16,6 +16,7 @@ package android.media; import android.util.IntArray; + import com.android.server.LocalServices; /** @@ -48,6 +49,18 @@ public abstract class AudioManagerInternal { public abstract void setAccessibilityServiceUids(IntArray uids); + /** + * Called by {@link com.android.server.inputmethod.InputMethodManagerService} to notify the UID + * of the currently used {@link android.inputmethodservice.InputMethodService}. + * + *

The caller is expected to take care of any performance implications, e.g. by using a + * background thread to call this method.

+ * + * @param uid UID of the currently used {@link android.inputmethodservice.InputMethodService}. + * {@link android.os.Process#INVALID_UID} if no IME is active. + */ + public abstract void setInputMethodServiceUid(int uid); + public interface RingerModeDelegate { /** Called when external ringer mode is evaluated, returns the new internal ringer mode */ int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 8068e378f2e36..e5a7daf9d1d3d 100755 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -52,7 +52,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; @@ -570,6 +569,10 @@ public class AudioService extends IAudioService.Stub private int[] mAccessibilityServiceUids; private final Object mAccessibilityServiceUidsLock = new Object(); + // Uid of the active input method service to check if caller is the one or not. + private int mInputMethodServiceUid = android.os.Process.INVALID_UID; + private final Object mInputMethodServiceUidLock = new Object(); + private int mEncodedSurroundMode; private String mEnabledSurroundFormats; private boolean mSurroundModeChanged; @@ -1078,12 +1081,14 @@ public class AudioService extends IAudioService.Stub sendEncodedSurroundMode(mContentResolver, "onAudioServerDied"); sendEnabledSurroundFormats(mContentResolver, true); updateAssistantUId(true); - updateCurrentImeUid(true); AudioSystem.setRttEnabled(mRttEnabled); } synchronized (mAccessibilityServiceUidsLock) { AudioSystem.setA11yServicesUids(mAccessibilityServiceUids); } + synchronized (mInputMethodServiceUidLock) { + mAudioSystem.setCurrentImeUid(mInputMethodServiceUid); + } synchronized (mHdmiClientLock) { if (mHdmiManager != null && mHdmiTvClient != null) { setHdmiSystemAudioSupported(mHdmiSystemAudioSupported); @@ -1629,37 +1634,6 @@ public class AudioService extends IAudioService.Stub } } - @GuardedBy("mSettingsLock") - private void updateCurrentImeUid(boolean forceUpdate) { - String imeId = Settings.Secure.getStringForUser( - mContentResolver, - Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT); - if (TextUtils.isEmpty(imeId)) { - Log.e(TAG, "updateCurrentImeUid() could not find current IME"); - return; - } - ComponentName componentName = ComponentName.unflattenFromString(imeId); - if (componentName == null) { - Log.e(TAG, "updateCurrentImeUid() got invalid service name for " - + Settings.Secure.DEFAULT_INPUT_METHOD + ": " + imeId); - return; - } - String packageName = componentName.getPackageName(); - int currentUserId = LocalServices.getService(ActivityManagerInternal.class) - .getCurrentUserId(); - int currentImeUid = LocalServices.getService(PackageManagerInternal.class) - .getPackageUidInternal(packageName, 0 /* flags */, currentUserId); - if (currentImeUid < 0) { - Log.e(TAG, "updateCurrentImeUid() could not find UID for package: " + packageName); - return; - } - - if (currentImeUid != mCurrentImeUid || forceUpdate) { - mAudioSystem.setCurrentImeUid(currentImeUid); - mCurrentImeUid = currentImeUid; - } - } - private void readPersistedSettings() { if (!mSystemServer.isPrivileged()) { return; @@ -1707,7 +1681,6 @@ public class AudioService extends IAudioService.Stub sendEncodedSurroundMode(cr, "readPersistedSettings"); sendEnabledSurroundFormats(cr, true); updateAssistantUId(true); - updateCurrentImeUid(true); AudioSystem.setRttEnabled(mRttEnabled); } @@ -6217,8 +6190,6 @@ public class AudioService extends IAudioService.Stub mContentResolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.VOICE_INTERACTION_SERVICE), false, this); - mContentResolver.registerContentObserver(Settings.Secure.getUriFor( - Settings.Secure.DEFAULT_INPUT_METHOD), false, this); } @Override @@ -6242,7 +6213,6 @@ public class AudioService extends IAudioService.Stub updateEncodedSurroundOutput(); sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged); updateAssistantUId(false); - updateCurrentImeUid(false); } } @@ -7584,6 +7554,19 @@ public class AudioService extends IAudioService.Stub AudioSystem.setA11yServicesUids(mAccessibilityServiceUids); } } + + /** + * {@inheritDoc} + */ + @Override + public void setInputMethodServiceUid(int uid) { + synchronized (mInputMethodServiceUidLock) { + if (mInputMethodServiceUid != uid) { + mAudioSystem.setCurrentImeUid(uid); + mInputMethodServiceUid = uid; + } + } + } } //========================================================================================== diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 93ef1264755b1..52116a07e8e6a 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -56,6 +56,7 @@ import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Configuration; @@ -67,6 +68,7 @@ import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManagerInternal; import android.hardware.input.InputManagerInternal; import android.inputmethodservice.InputMethodService; +import android.media.AudioManagerInternal; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -223,6 +225,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final int MSG_INLINE_SUGGESTIONS_REQUEST = 6000; + static final int MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE = 7000; + static final long TIME_TO_RECONNECT = 3 * 1000; static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20; @@ -308,6 +312,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final SettingsObserver mSettingsObserver; final IWindowManager mIWindowManager; final WindowManagerInternal mWindowManagerInternal; + final PackageManagerInternal mPackageManagerInternal; final InputManagerInternal mInputManagerInternal; private final DisplayManagerInternal mDisplayManagerInternal; final HandlerCaller mCaller; @@ -320,6 +325,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final UserManager mUserManager; private final UserManagerInternal mUserManagerInternal; + /** + * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}. + * + *

This field is used only within {@link #handleMessage(Message)} hence synchronization is + * not necessary.

+ */ + @Nullable + private AudioManagerInternal mAudioManagerInternal = null; + + // All known input methods. mMethodMap also serves as the global // lock for this class. final ArrayList mMethodList = new ArrayList<>(); @@ -642,6 +657,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ IInputMethod mCurMethod; + /** + * If not {@link Process#INVALID_UID}, then the UID of {@link #mCurIntent}. + */ + int mCurMethodUid = Process.INVALID_UID; + /** * Time that we last initiated a bind to the input method, to determine * if we should try to disconnect and reconnect to it. @@ -1625,6 +1645,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); + mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mImeDisplayValidator = displayId -> mWindowManagerInternal.shouldShowIme(displayId); @@ -2521,11 +2542,26 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return checker.displayCanShowIme(displayId) ? displayId : FALLBACK_DISPLAY_ID; } + @AnyThread + private void scheduleNotifyImeUidToAudioService(int uid) { + mCaller.removeMessages(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE); + mCaller.obtainMessageI(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE, uid).sendToTarget(); + } + @Override public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mMethodMap) { if (mCurIntent != null && name.equals(mCurIntent.getComponent())) { mCurMethod = IInputMethod.Stub.asInterface(service); + final String curMethodPackage = mCurIntent.getComponent().getPackageName(); + final int curMethodUid = mPackageManagerInternal.getPackageUidInternal( + curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId()); + if (curMethodUid < 0) { + Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage); + mCurMethodUid = Process.INVALID_UID; + } else { + mCurMethodUid = curMethodUid; + } if (mCurToken == null) { Slog.w(TAG, "Service connected without a token!"); unbindCurrentMethodLocked(); @@ -2535,6 +2571,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Dispatch display id for InputMethodService to update context display. executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO( MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken)); + scheduleNotifyImeUidToAudioService(mCurMethodUid); if (mCurClient != null) { clearClientSessionLocked(mCurClient); requestClientSessionLocked(mCurClient); @@ -2656,6 +2693,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub finishSessionLocked(mEnabledSession); mEnabledSession = null; mCurMethod = null; + mCurMethodUid = Process.INVALID_UID; + scheduleNotifyImeUidToAudioService(mCurMethodUid); } if (mStatusBar != null) { mStatusBar.setIconVisibility(mSlotIme, false); @@ -4277,6 +4316,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub args.recycle(); return true; } + + // --------------------------------------------------------------- + case MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE: { + if (mAudioManagerInternal == null) { + mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); + } + if (mAudioManagerInternal != null) { + mAudioManagerInternal.setInputMethodServiceUid(msg.arg1 /* uid */); + } + return true; + } } return false; }