OSDN Git Service

Use a flag to grant a temporary URI permission.
authorYohei Yukawa <yukawa@google.com>
Fri, 24 Jun 2016 00:12:59 +0000 (17:12 -0700)
committerYohei Yukawa <yukawa@google.com>
Fri, 24 Jun 2016 00:12:59 +0000 (17:12 -0700)
It turns out that we can let the system to call
InputMethodService#exposeContent(InputContentInfo, EditorInfo), which
added in my previous CL [1], during the IME is calling
InputConnection#commitContent() as follows.

  [IME]
  InputContentInfo contentInfo = new InputContentInfo(
          contentUri,
          new ClipDescription(description, new String[]{mimeType}),
          linkUrl);
  getCurrentInputConnection().commitContent(
          inputContentInfo,
          InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION,
          null);

  [App]
  try {
      contentInfo.requestPermission();
      // Load inputContentInfo.getContentUri() here.
  } finally {
      contentInfo.releasePermission();
  }

This gives us flexibility to let InputConnection#commitContent() do all
the magic for IME developers like other APIs such as
Context#startActivity(), rather than asking them to call one more API to
grant a temporary URI permission like a scenario where
Context#grantUriPermission() is used.

 [1]: I2772889ca01f2ecb2cdeed4e04a9319bdf7bc5a6
      25e0813e6eb6315b1016db805fa9b791b4ae5cc2

Bug: 29450031
Change-Id: I99536cd58c9984af30b0bafb4a1dd25a26634a2d

16 files changed:
api/current.txt
api/system-current.txt
api/test-current.txt
core/java/android/inputmethodservice/AbstractInputMethodService.java
core/java/android/inputmethodservice/IInputMethodWrapper.java
core/java/android/inputmethodservice/InputMethodService.java
core/java/android/view/inputmethod/BaseInputConnection.java
core/java/android/view/inputmethod/EditorInfo.java
core/java/android/view/inputmethod/InputConnection.java
core/java/android/view/inputmethod/InputConnectionInspector.java
core/java/android/view/inputmethod/InputConnectionWrapper.java
core/java/android/view/inputmethod/InputMethodManager.java
core/java/android/widget/AbsListView.java
core/java/com/android/internal/view/IInputConnectionWrapper.java
core/java/com/android/internal/view/IInputContext.aidl
core/java/com/android/internal/view/InputConnectionWrapper.java

index 8477bb5..f95c541 100644 (file)
@@ -18857,7 +18857,6 @@ package android.inputmethodservice {
   public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService {
     ctor public InputMethodService();
     method public deprecated boolean enableHardwareAcceleration();
-    method public final boolean exposeContent(android.view.inputmethod.InputContentInfo, android.view.inputmethod.EditorInfo);
     method public int getBackDisposition();
     method public int getCandidatesHiddenVisibility();
     method public android.view.inputmethod.InputBinding getCurrentInputBinding();
@@ -44698,7 +44697,7 @@ package android.view.inputmethod {
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -44868,7 +44867,7 @@ package android.view.inputmethod {
     method public abstract boolean clearMetaKeyStates(int);
     method public abstract void closeConnection();
     method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public abstract boolean commitText(java.lang.CharSequence, int);
     method public abstract boolean deleteSurroundingText(int, int);
@@ -44894,6 +44893,7 @@ package android.view.inputmethod {
     field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
     field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
     field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+    field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
   }
 
   public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -44902,7 +44902,7 @@ package android.view.inputmethod {
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
index 1095ac3..6a23b6e 100644 (file)
@@ -20057,7 +20057,6 @@ package android.inputmethodservice {
   public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService {
     ctor public InputMethodService();
     method public deprecated boolean enableHardwareAcceleration();
-    method public final boolean exposeContent(android.view.inputmethod.InputContentInfo, android.view.inputmethod.EditorInfo);
     method public int getBackDisposition();
     method public int getCandidatesHiddenVisibility();
     method public android.view.inputmethod.InputBinding getCurrentInputBinding();
@@ -47805,7 +47804,7 @@ package android.view.inputmethod {
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -47975,7 +47974,7 @@ package android.view.inputmethod {
     method public abstract boolean clearMetaKeyStates(int);
     method public abstract void closeConnection();
     method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public abstract boolean commitText(java.lang.CharSequence, int);
     method public abstract boolean deleteSurroundingText(int, int);
@@ -48001,6 +48000,7 @@ package android.view.inputmethod {
     field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
     field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
     field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+    field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
   }
 
   public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -48009,7 +48009,7 @@ package android.view.inputmethod {
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
index 9e775a5..e688dcd 100644 (file)
@@ -18871,7 +18871,6 @@ package android.inputmethodservice {
   public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService {
     ctor public InputMethodService();
     method public deprecated boolean enableHardwareAcceleration();
-    method public final boolean exposeContent(android.view.inputmethod.InputContentInfo, android.view.inputmethod.EditorInfo);
     method public int getBackDisposition();
     method public int getCandidatesHiddenVisibility();
     method public android.view.inputmethod.InputBinding getCurrentInputBinding();
@@ -44778,7 +44777,7 @@ package android.view.inputmethod {
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -44948,7 +44947,7 @@ package android.view.inputmethod {
     method public abstract boolean clearMetaKeyStates(int);
     method public abstract void closeConnection();
     method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public abstract boolean commitText(java.lang.CharSequence, int);
     method public abstract boolean deleteSurroundingText(int, int);
@@ -44974,6 +44973,7 @@ package android.view.inputmethod {
     field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
     field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
     field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+    field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
   }
 
   public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -44982,7 +44982,7 @@ package android.view.inputmethod {
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
-    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
index 3531926..29177b6 100644 (file)
 
 package android.inputmethodservice;
 
+import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
 import android.view.inputmethod.InputMethod;
 import android.view.inputmethod.InputMethodSession;
 
@@ -208,7 +211,7 @@ public abstract class AbstractInputMethodService extends Service
      *
      * @param event The motion event being received.
      * @return True if the event was handled in this function, false otherwise.
-     * @see View#onTrackballEvent
+     * @see android.view.View#onTrackballEvent(MotionEvent)
      */
     public boolean onTrackballEvent(MotionEvent event) {
         return false;
@@ -219,9 +222,30 @@ public abstract class AbstractInputMethodService extends Service
      *
      * @param event The motion event being received.
      * @return True if the event was handled in this function, false otherwise.
-     * @see View#onGenericMotionEvent
+     * @see android.view.View#onGenericMotionEvent(MotionEvent)
      */
     public boolean onGenericMotionEvent(MotionEvent event) {
         return false;
     }
+
+    /**
+     * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+     * permission to the content.
+     *
+     * <p>Default implementation does nothing.</p>
+     *
+     * @param inputContentInfo Content to be temporarily exposed from the input method to the
+     * application.
+     * This cannot be {@code null}.
+     * @param inputConnection {@link InputConnection} with which
+     * {@link InputConnection#commitContent(InputContentInfo, int, android.os.Bundle)} will be
+     * called.
+     * @return {@code false} if we cannot allow a temporary access permission.
+     * @hide
+     */
+    public void exposeContent(@NonNull InputContentInfo inputContentInfo,
+            @NonNull InputConnection inputConnection) {
+        return;
+    }
+
 }
index cc71a9c..167d5a0 100644 (file)
@@ -168,7 +168,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
                 int missingMethods = msg.arg1;
                 IInputContext inputContext = (IInputContext)args.arg1;
                 InputConnection ic = inputContext != null
-                        ? new InputConnectionWrapper(inputContext, missingMethods) : null;
+                        ? new InputConnectionWrapper(mTarget, inputContext, missingMethods) : null;
                 EditorInfo info = (EditorInfo)args.arg2;
                 info.makeCompatible(mTargetSdkVersion);
                 inputMethod.startInput(ic, info);
@@ -180,7 +180,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
                 int missingMethods = msg.arg1;
                 IInputContext inputContext = (IInputContext)args.arg1;
                 InputConnection ic = inputContext != null
-                        ? new InputConnectionWrapper(inputContext, missingMethods) : null;
+                        ? new InputConnectionWrapper(mTarget, inputContext, missingMethods) : null;
                 EditorInfo info = (EditorInfo)args.arg2;
                 info.makeCompatible(mTargetSdkVersion);
                 inputMethod.restartInput(ic, info);
@@ -251,7 +251,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
     public void bindInput(InputBinding binding) {
         // This IInputContext is guaranteed to implement all the methods.
         final int missingMethodFlags = 0;
-        InputConnection ic = new InputConnectionWrapper(
+        InputConnection ic = new InputConnectionWrapper(mTarget,
                 IInputContext.Stub.asInterface(binding.getConnectionToken()), missingMethodFlags);
         InputBinding nu = new InputBinding(ic, binding);
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
index 8e0e0b0..fede77d 100644 (file)
@@ -2603,33 +2603,23 @@ public class InputMethodService extends AbstractInputMethodService {
      * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
      * permission to the content.
      *
-     * <p>Make sure that the content provider owning the Uri sets the
-     * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
-     * grantUriPermissions} attribute in its manifest or included the
-     * {@link android.R.styleable#AndroidManifestGrantUriPermission
-     * &lt;grant-uri-permissions&gt;} tag. Otherwise {@link InputContentInfo#requestPermission()}
-     * can fail.</p>
-     *
-     * <p>Although calling this API is allowed only for the IME that is currently selected, the
-     * client is able to request a temporary read-only access even after the current IME is switched
-     * to any other IME as long as the client keeps {@link InputContentInfo} object.</p>
-     *
      * @param inputContentInfo Content to be temporarily exposed from the input method to the
      * application.
      * This cannot be {@code null}.
-     * @param editorInfo The editor that receives {@link InputContentInfo}.
-     * @return {@code false} if we cannot allow a temporary access permission.
+     * @param inputConnection {@link InputConnection} with which
+     * {@link InputConnection#commitContent(InputContentInfo, Bundle)} will be called.
+     * @hide
      */
-    public final boolean exposeContent(@NonNull InputContentInfo inputContentInfo,
-            @NonNull EditorInfo editorInfo) {
-        if (inputContentInfo == null) {
-            throw new NullPointerException("inputContentInfo");
+    @Override
+    public final void exposeContent(@NonNull InputContentInfo inputContentInfo,
+            @NonNull InputConnection inputConnection) {
+        if (inputConnection == null) {
+            return;
         }
-        if (editorInfo == null) {
-            throw new NullPointerException("editorInfo");
+        if (getCurrentInputConnection() != inputConnection) {
+            return;
         }
-
-        return mImm.exposeContent(mToken, inputContentInfo, editorInfo);
+        mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo());
     }
 
     /**
index 0ebbf7f..38962a3 100644 (file)
@@ -855,5 +855,7 @@ public class BaseInputConnection implements InputConnection {
     /**
      * The default implementation does nothing.
      */
-    public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) { return false; }
+    public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+        return false;
+    }
 }
index 2dca892..8038089 100644 (file)
@@ -368,10 +368,10 @@ public class EditorInfo implements InputType, Parcelable {
 
     /**
      * List of acceptable MIME types for
-     * {@link InputConnection#commitContent(InputContentInfo, Bundle)}.
+     * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)}.
      *
      * <p>{@code null} or an empty array means that
-     * {@link InputConnection#commitContent(InputContentInfo, Bundle)} is not supported in this
+     * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is not supported in this
      * editor.</p>
      */
     @Nullable
index f7f3694..07910b6 100644 (file)
@@ -840,6 +840,24 @@ public interface InputConnection {
     public void closeConnection();
 
     /**
+     * When this flag is used, the editor will be able to request read access to the content URI
+     * contained in the {@link InputContentInfo} object.
+     *
+     * <p>Make sure that the content provider owning the Uri sets the
+     * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
+     * grantUriPermissions} attribute in its manifest or included the
+     * {@link android.R.styleable#AndroidManifestGrantUriPermission
+     * &lt;grant-uri-permissions&gt;} tag. Otherwise {@link InputContentInfo#requestPermission()}
+     * can fail.</p>
+     *
+     * <p>Although calling this API is allowed only for the IME that is currently selected, the
+     * client is able to request a temporary read-only access even after the current IME is switched
+     * to any other IME as long as the client keeps {@link InputContentInfo} object.</p>
+     **/
+    public static int INPUT_CONTENT_GRANT_READ_URI_PERMISSION =
+            android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;  // 0x00000001
+
+    /**
      * Called by the input method to commit a content such as PNG image to the editor.
      *
      * <p>In order to avoid variety of compatibility issues, this focuses on a simple use case,
@@ -862,9 +880,11 @@ public interface InputConnection {
      * </ul>
      *
      * @param inputContentInfo Content to be inserted.
+     * @param flags {@code 0} or {@link #INPUT_CONTENT_GRANT_READ_URI_PERMISSION}.
      * @param opts optional bundle data. This can be {@code null}.
      * @return {@code true} if this request is accepted by the application, no matter if the request
      * is already handled or still being handled in background.
      */
-    public boolean commitContent(@NonNull InputContentInfo inputContentInfo, @Nullable Bundle opts);
+    public boolean commitContent(@NonNull InputContentInfo inputContentInfo, int flags,
+            @Nullable Bundle opts);
 }
index 727e9ca..2b292bb 100644 (file)
@@ -82,7 +82,7 @@ public final class InputConnectionInspector {
          */
         int CLOSE_CONNECTION = 1 << 6;
         /**
-         * {@link InputConnection#commitContent(InputContentInfo, Bundle)} is available in
+         * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is available in
          * {@link android.os.Build.VERSION_CODES#N} MR-1 and later.
          */
         int COMMIT_CONTENT = 1 << 7;
@@ -209,7 +209,7 @@ public final class InputConnectionInspector {
     private static boolean hasCommitContent(@NonNull final Class clazz) {
         try {
             final Method method = clazz.getMethod("commitContent", InputContentInfo.class,
-                    Bundle.class);
+                    int.class, Bundle.class);
             return !Modifier.isAbstract(method.getModifiers());
         } catch (NoSuchMethodException e) {
             return false;
index af9bcae..317730c 100644 (file)
@@ -274,7 +274,7 @@ public class InputConnectionWrapper implements InputConnection {
      * {@inheritDoc}
      * @throws NullPointerException if the target is {@code null}.
      */
-    public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) {
-        return mTarget.commitContent(inputContentInfo, opts);
+    public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+        return mTarget.commitContent(inputContentInfo, flags, opts);
     }
 }
index b35f5c3..c0c8e64 100644 (file)
@@ -2304,10 +2304,9 @@ public final class InputMethodManager {
      * application.
      * This cannot be {@code null}.
      * @param editorInfo The editor that receives {@link InputContentInfo}.
-     * @return {@code false} if we cannot allow a temporary access permission.
      * @hide
      */
-    public boolean exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
+    public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
             @NonNull EditorInfo editorInfo) {
         final IInputContentUriToken uriToken;
         final Uri contentUri = inputContentInfo.getContentUri();
@@ -2315,15 +2314,15 @@ public final class InputMethodManager {
             uriToken = mService.createInputContentUriToken(token, contentUri,
                     editorInfo.packageName);
             if (uriToken == null) {
-                return false;
+                return;
             }
         } catch (RemoteException e) {
             Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
                     + " packageName=" + editorInfo.packageName, e);
-            return false;
+            return;
         }
         inputContentInfo.setUriToken(uriToken);
-        return true;
+        return;
     }
 
     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
index f296421..7d7b880 100644 (file)
@@ -5985,8 +5985,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
         }
 
         @Override
-        public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) {
-            return getTarget().commitContent(inputContentInfo, opts);
+        public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+            return getTarget().commitContent(inputContentInfo, flags, opts);
         }
     }
 
index dce9d2c..62e34a6 100644 (file)
@@ -243,9 +243,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
         dispatchMessage(obtainMessage(DO_CLOSE_CONNECTION));
     }
 
-    public void commitContent(InputContentInfo inputContentInfo, Bundle opts,
+    public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts,
             int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageOOSC(DO_COMMIT_CONTENT, inputContentInfo, opts, seq, callback));
+        dispatchMessage(obtainMessageIOOSC(DO_COMMIT_CONTENT, flags, inputContentInfo, opts, seq,
+                callback));
     }
 
     void dispatchMessage(Message msg) {
@@ -560,6 +561,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
                 return;
             }
             case DO_COMMIT_CONTENT: {
+                final int flags = msg.arg1;
                 SomeArgs args = (SomeArgs) msg.obj;
                 try {
                     InputConnection ic = getInputConnection();
@@ -576,7 +578,8 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
                         return;
                     }
                     args.callback.setCommitContentResult(
-                            ic.commitContent(inputContentInfo, (Bundle) args.arg2), args.seq);
+                            ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2),
+                            args.seq);
                 } catch (RemoteException e) {
                     Log.w(TAG, "Got RemoteException calling commitContent", e);
                 }
@@ -612,14 +615,14 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
         return mH.obtainMessage(what, arg1, arg2, args);
     }
 
-    Message obtainMessageOOSC(int what, Object arg1, Object arg2, int seq,
+    Message obtainMessageIOOSC(int what, int arg1, Object objArg1, Object objArg2, int seq,
             IInputContextCallback callback) {
         SomeArgs args = new SomeArgs();
-        args.arg1 = arg1;
-        args.arg2 = arg2;
+        args.arg1 = objArg1;
+        args.arg2 = objArg2;
         args.callback = callback;
         args.seq = seq;
-        return mH.obtainMessage(what, 0, 0, args);
+        return mH.obtainMessage(what, arg1, 0, args);
     }
 
     Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq,
index 0d5c8a1..728c557 100644 (file)
@@ -78,6 +78,6 @@ import com.android.internal.view.IInputContextCallback;
     void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
             IInputContextCallback callback);
 
-    void commitContent(in InputContentInfo inputContentInfo, in Bundle opts, int sec,
+    void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, int sec,
             IInputContextCallback callback);
 }
index 5e78ec5..9a09dcc 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.internal.view;
 
+import android.annotation.NonNull;
+import android.inputmethodservice.AbstractInputMethodService;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -31,9 +33,14 @@ import android.view.inputmethod.InputConnectionInspector;
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputContentInfo;
 
+import java.lang.ref.WeakReference;
+
 public class InputConnectionWrapper implements InputConnection {
     private static final int MAX_WAIT_TIME_MILLIS = 2000;
     private final IInputContext mIInputContext;
+    @NonNull
+    private final WeakReference<AbstractInputMethodService> mInputMethodService;
+
     @MissingMethodFlags
     private final int mMissingMethods;
 
@@ -210,8 +217,10 @@ public class InputConnectionWrapper implements InputConnection {
         }
     }
 
-    public InputConnectionWrapper(IInputContext inputContext,
-            @MissingMethodFlags final int missingMethods) {
+    public InputConnectionWrapper(
+            @NonNull WeakReference<AbstractInputMethodService> inputMethodService,
+            IInputContext inputContext, @MissingMethodFlags final int missingMethods) {
+        mInputMethodService = inputMethodService;
         mIInputContext = inputContext;
         mMissingMethods = missingMethods;
     }
@@ -506,15 +515,24 @@ public class InputConnectionWrapper implements InputConnection {
         // Nothing should happen when called from input method.
     }
 
-    public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) {
+    public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
         boolean result = false;
         if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
             // This method is not implemented.
             return false;
         }
         try {
+            if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
+                final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+                if (inputMethodService == null) {
+                    // This basically should not happen, because it's the the caller of this method.
+                    return false;
+                }
+                inputMethodService.exposeContent(inputContentInfo, this);
+            }
+
             InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.commitContent(inputContentInfo, opts, callback.mSeq, callback);
+            mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
             synchronized (callback) {
                 callback.waitForResultLocked();
                 if (callback.mHaveValue) {