diff options
-rw-r--r-- | cmds/ime/Android.mk | 7 | ||||
-rwxr-xr-x | cmds/ime/ime | 8 | ||||
-rw-r--r-- | cmds/ime/src/com/android/commands/ime/Ime.java | 248 | ||||
-rw-r--r-- | core/java/com/android/internal/view/IInputMethodManager.aidl | 1 | ||||
-rw-r--r-- | services/core/java/com/android/server/InputMethodManagerService.java | 203 |
5 files changed, 180 insertions, 287 deletions
diff --git a/cmds/ime/Android.mk b/cmds/ime/Android.mk index 6803fc01154c..ca608e8c2c34 100644 --- a/cmds/ime/Android.mk +++ b/cmds/ime/Android.mk @@ -3,14 +3,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_MODULE := imelib -LOCAL_MODULE_STEM := ime -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) LOCAL_MODULE := ime LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := ime -LOCAL_REQUIRED_MODULES := imelib include $(BUILD_PREBUILT) diff --git a/cmds/ime/ime b/cmds/ime/ime index 1a1fdd96da6e..180dc761055b 100755 --- a/cmds/ime/ime +++ b/cmds/ime/ime @@ -1,8 +1,2 @@ #!/system/bin/sh -# Script to start "pm" on the device, which has a very rudimentary -# shell. -# -base=/system -export CLASSPATH=$base/framework/ime.jar -exec app_process $base/bin com.android.commands.ime.Ime "$@" - +exec cmd input_method "$@" diff --git a/cmds/ime/src/com/android/commands/ime/Ime.java b/cmds/ime/src/com/android/commands/ime/Ime.java deleted file mode 100644 index 72a0af6c2d99..000000000000 --- a/cmds/ime/src/com/android/commands/ime/Ime.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2007 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.commands.ime; - -import com.android.internal.view.IInputMethodManager; - -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.PrintStreamPrinter; -import android.util.Printer; -import android.view.inputmethod.InputMethodInfo; - -import java.util.List; - -public final class Ime { - IInputMethodManager mImm; - - private String[] mArgs; - private int mNextArg; - private String mCurArgData; - - private static final String IMM_NOT_RUNNING_ERR = - "Error: Could not access the Input Method Manager. Is the system running?"; - - public static void main(String[] args) { - new Ime().run(args); - } - - public void run(String[] args) { - if (args.length < 1) { - showUsage(); - return; - } - - mImm = IInputMethodManager.Stub.asInterface(ServiceManager.getService("input_method")); - if (mImm == null) { - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - - mArgs = args; - String op = args[0]; - mNextArg = 1; - - if ("list".equals(op)) { - runList(); - return; - } - - if ("enable".equals(op)) { - runSetEnabled(true); - return; - } - - if ("disable".equals(op)) { - runSetEnabled(false); - return; - } - - if ("set".equals(op)) { - runSet(); - return; - } - - if (op != null) { - System.err.println("Error: unknown command '" + op + "'"); - } - showUsage(); - } - - /** - * Execute the list sub-command. - */ - private void runList() { - String opt; - boolean all = false; - boolean brief = false; - while ((opt=nextOption()) != null) { - if (opt.equals("-a")) { - all = true; - } else if (opt.equals("-s")) { - brief = true; - } else { - System.err.println("Error: Unknown option: " + opt); - showUsage(); - return; - } - } - - - List<InputMethodInfo> methods; - if (!all) { - try { - methods = mImm.getEnabledInputMethodList(); - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } else { - try { - methods = mImm.getInputMethodList(); - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } - - if (methods != null) { - Printer pr = new PrintStreamPrinter(System.out); - for (int i=0; i<methods.size(); i++) { - InputMethodInfo imi = methods.get(i); - if (brief) { - System.out.println(imi.getId()); - } else { - System.out.println(imi.getId() + ":"); - imi.dump(pr, " "); - } - } - } - } - - private void runSetEnabled(boolean state) { - String id = nextArg(); - if (id == null) { - System.err.println("Error: no input method ID specified"); - showUsage(); - return; - } - - try { - boolean res = mImm.setInputMethodEnabled(id, state); - if (state) { - System.out.println("Input method " + id + ": " - + (res ? "already enabled" : "now enabled")); - } else { - System.out.println("Input method " + id + ": " - + (res ? "now disabled" : "already disabled")); - } - } catch (IllegalArgumentException e) { - System.err.println("Error: " + e.getMessage()); - return; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } - - private void runSet() { - String id = nextArg(); - if (id == null) { - System.err.println("Error: no input method ID specified"); - showUsage(); - return; - } - - try { - mImm.setInputMethod(null, id); - System.out.println("Input method " + id + " selected"); - } catch (IllegalArgumentException e) { - System.err.println("Error: " + e.getMessage()); - return; - } catch (RemoteException e) { - System.err.println(e.toString()); - System.err.println(IMM_NOT_RUNNING_ERR); - return; - } - } - - private String nextOption() { - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - if (!arg.startsWith("-")) { - return null; - } - mNextArg++; - if (arg.equals("--")) { - return null; - } - if (arg.length() > 1 && arg.charAt(1) != '-') { - if (arg.length() > 2) { - mCurArgData = arg.substring(2); - return arg.substring(0, 2); - } else { - mCurArgData = null; - return arg; - } - } - mCurArgData = null; - return arg; - } - - private String nextOptionData() { - if (mCurArgData != null) { - return mCurArgData; - } - if (mNextArg >= mArgs.length) { - return null; - } - String data = mArgs[mNextArg]; - mNextArg++; - return data; - } - - private String nextArg() { - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - mNextArg++; - return arg; - } - - private static void showUsage() { - System.err.println("usage: ime list [-a] [-s]"); - System.err.println(" ime enable ID"); - System.err.println(" ime disable ID"); - System.err.println(" ime set ID"); - System.err.println(""); - System.err.println("The list command prints all enabled input methods. Use"); - System.err.println("the -a option to see all input methods. Use"); - System.err.println("the -s option to see only a single summary line of each."); - System.err.println(""); - System.err.println("The enable command allows the given input method ID to be used."); - System.err.println(""); - System.err.println("The disable command disallows the given input method ID from use."); - System.err.println(""); - System.err.println("The set command switches to the given input method ID."); - } -} diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index ca8624d9c01e..1fd5564773b1 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -80,7 +80,6 @@ interface IInputMethodManager { boolean switchToLastInputMethod(in IBinder token); boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme); boolean shouldOfferSwitchingToNextInputMethod(in IBinder token); - boolean setInputMethodEnabled(String id, boolean enabled); void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes); int getInputMethodWindowVisibleHeight(); void clearLastInputMethodWindowForTransition(in IBinder token); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 37f1dc490fe3..e1d6b5da0db8 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -49,12 +49,14 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.Manifest; import android.annotation.BinderThread; import android.annotation.ColorInt; import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -104,6 +106,8 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; +import android.os.ShellCallback; +import android.os.ShellCommand; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -178,6 +182,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final boolean DEBUG_RESTORE = DEBUG || false; static final String TAG = "InputMethodManagerService"; + @Retention(SOURCE) + @IntDef({ShellCommandResult.SUCCESS, ShellCommandResult.FAILURE}) + private @interface ShellCommandResult { + int SUCCESS = 0; + int FAILURE = -1; + } + static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1; static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2; static final int MSG_SHOW_IM_CONFIG = 3; @@ -3885,30 +3896,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // ---------------------------------------------------------------------- - @Override - public boolean setInputMethodEnabled(String id, boolean enabled) { - // TODO: Make this work even for non-current users? - if (!calledFromValidUser()) { - return false; - } - synchronized (mMethodMap) { - if (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.WRITE_SECURE_SETTINGS) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException( - "Requires permission " - + android.Manifest.permission.WRITE_SECURE_SETTINGS); - } - - long ident = Binder.clearCallingIdentity(); - try { - return setInputMethodEnabledLocked(id, enabled); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - boolean setInputMethodEnabledLocked(String id, boolean enabled) { // Make sure this is a valid input method. InputMethodInfo imm = mMethodMap.get(id); @@ -4633,4 +4620,172 @@ public class InputMethodManagerService extends IInputMethodManager.Stub p.println("No input method service."); } } + + @BinderThread + @Override + public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out, + @Nullable FileDescriptor err, + @NonNull String[] args, @Nullable ShellCallback callback, + @NonNull ResultReceiver resultReceiver) throws RemoteException { + new ShellCommandImpl(this).exec( + this, in, out, err, args, callback, resultReceiver); + } + + private static final class ShellCommandImpl extends ShellCommand { + @NonNull + final InputMethodManagerService mService; + + ShellCommandImpl(InputMethodManagerService service) { + mService = service; + } + + @BinderThread + @ShellCommandResult + @Override + public int onCommand(@Nullable String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + switch (cmd) { + case "list": + return mService.handleShellCommandListInputMethods(this); + case "enable": + return mService.handleShellCommandEnableDisableInputMethod(this, true); + case "disable": + return mService.handleShellCommandEnableDisableInputMethod(this, false); + case "set": + return mService.handleShellCommandSetInputMethod(this); + default: + return handleDefaultCommands(cmd); + } + } + + @BinderThread + @Override + public void onHelp() { + try (PrintWriter pw = getOutPrintWriter()) { + pw.println("InputMethodManagerService commands:"); + pw.println(" help"); + pw.println(" Prints this help text."); + pw.println(" dump [options]"); + pw.println(" Synonym of dumpsys."); + pw.println(" list [-a] [-s]"); + pw.println(" prints all enabled input methods."); + pw.println(" -a: see all input methods"); + pw.println(" -s: only a single summary line of each"); + pw.println(" enable <ID>"); + pw.println(" allows the given input method ID to be used."); + pw.println(" disable <ID>"); + pw.println(" disallows the given input method ID to be used."); + pw.println(" set <ID>"); + pw.println(" switches to the given input method ID."); + } + } + } + + // ---------------------------------------------------------------------- + // Shell command handlers: + + /** + * Handles {@code adb shell ime list}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + private int handleShellCommandListInputMethods(@NonNull ShellCommand shellCommand) { + boolean all = false; + boolean brief = false; + while (true) { + final String nextOption = shellCommand.getNextOption(); + if (nextOption == null) { + break; + } + switch (nextOption) { + case "-a": + all = true; + break; + case "-s": + brief = true; + break; + } + } + final List<InputMethodInfo> methods = all ? + getInputMethodList() : getEnabledInputMethodList(); + final PrintWriter pr = shellCommand.getOutPrintWriter(); + final Printer printer = x -> pr.println(x); + final int N = methods.size(); + for (int i = 0; i < N; ++i) { + if (brief) { + pr.println(methods.get(i).getId()); + } else { + pr.print(methods.get(i).getId()); pr.println(":"); + methods.get(i).dump(printer, " "); + } + } + return ShellCommandResult.SUCCESS; + } + + /** + * Handles {@code adb shell ime enable} and {@code adb shell ime disable}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @param enabled {@code true} if the command was {@code adb shell ime enable}. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + private int handleShellCommandEnableDisableInputMethod( + @NonNull ShellCommand shellCommand, boolean enabled) { + if (!calledFromValidUser()) { + shellCommand.getErrPrintWriter().print( + "Must be called from the foreground user or with INTERACT_ACROSS_USERS_FULL"); + return ShellCommandResult.FAILURE; + } + final String id = shellCommand.getNextArgRequired(); + + final boolean previouslyEnabled; + synchronized (mMethodMap) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) + != PackageManager.PERMISSION_GRANTED) { + shellCommand.getErrPrintWriter().print( + "Caller must have WRITE_SECURE_SETTINGS permission"); + throw new SecurityException( + "Requires permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + + final long ident = Binder.clearCallingIdentity(); + try { + previouslyEnabled = setInputMethodEnabledLocked(id, enabled); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + final PrintWriter pr = shellCommand.getOutPrintWriter(); + pr.print("Input method "); + pr.print(id); + pr.print(": "); + pr.print((enabled == previouslyEnabled) ? "already " : "now "); + pr.println(enabled ? "enabled" : "disabled"); + return ShellCommandResult.SUCCESS; + } + + /** + * Handles {@code adb shell ime set}. + * @param shellCommand {@link ShellCommand} object that is handling this command. + * @return Exit code of the command. + */ + @BinderThread + @ShellCommandResult + private int handleShellCommandSetInputMethod(@NonNull ShellCommand shellCommand) { + final String id = shellCommand.getNextArgRequired(); + setInputMethod(null, id); + final PrintWriter pr = shellCommand.getOutPrintWriter(); + pr.print("Input method "); + pr.print(id); + pr.println(" selected"); + return ShellCommandResult.SUCCESS; + } } |