Merge "Revert "Remove InputContentInfo#requestPermission()"" into nyc-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 237dafb..0323098f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44923,6 +44923,7 @@
method public android.content.ClipDescription getDescription();
method public android.net.Uri getLinkUri();
method public void releasePermission();
+ method public void requestPermission();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.inputmethod.InputContentInfo> CREATOR;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index a06c36a..aa1d74c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -48091,6 +48091,7 @@
method public android.content.ClipDescription getDescription();
method public android.net.Uri getLinkUri();
method public void releasePermission();
+ method public void requestPermission();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.inputmethod.InputContentInfo> CREATOR;
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 361161c..d904415 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -45003,6 +45003,7 @@
method public android.content.ClipDescription getDescription();
method public android.net.Uri getLinkUri();
method public void releasePermission();
+ method public void requestPermission();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.inputmethod.InputContentInfo> CREATOR;
}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index ecfcbc5..07910b6 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -840,16 +840,15 @@
public void closeConnection();
/**
- * When this flag is used in {@link #commitContent(InputContentInfo, int, Bundle)}, the editor
- * will be able to request read access to the content URI contained in the
- * {@link InputContentInfo} object.
+ * 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
- * <grant-uri-permissions>} tag. Otherwise
- * {@link #commitContent(InputContentInfo, int, Bundle)} can fail.</p>
+ * <grant-uri-permissions>} 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
diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java
index df20643..9579bbf 100644
--- a/core/java/android/view/inputmethod/InputContentInfo.java
+++ b/core/java/android/view/inputmethod/InputContentInfo.java
@@ -163,6 +163,22 @@
}
/**
+ * Requests a temporary read-only access permission for content URI associated with this object.
+ *
+ * <p>Does nothing if the temporary permission is already granted.</p>
+ */
+ public void requestPermission() {
+ if (mUriToken == null) {
+ return;
+ }
+ try {
+ mUriToken.take();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Releases a temporary read-only access permission for content URI associated with this object.
*
* <p>Does nothing if the temporary permission is not granted.</p>
diff --git a/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl b/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl
index c259348..8abc807 100644
--- a/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl
@@ -22,5 +22,6 @@
* {@hide}
*/
interface IInputContentUriToken {
+ void take();
void release();
}
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 15422b6..9a09dcc 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -517,22 +517,20 @@
public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
boolean result = false;
- final boolean grantUriPermission =
- (flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0;
if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
// This method is not implemented.
return false;
}
try {
- if (grantUriPermission) {
+ 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;
}
- // Temporarily grant URI permission.
inputMethodService.exposeContent(inputContentInfo, this);
}
+
InputContextCallback callback = InputContextCallback.getInstance();
mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
synchronized (callback) {
@@ -542,10 +540,6 @@
}
}
callback.dispose();
- // If this request is not handled, then there is no reason to keep the URI permission.
- if (grantUriPermission && !result) {
- inputContentInfo.releasePermission();
- }
} catch (RemoteException e) {
return false;
}
diff --git a/services/core/java/com/android/server/InputContentUriTokenHandler.java b/services/core/java/com/android/server/InputContentUriTokenHandler.java
index 12e1d62..3f4972b 100644
--- a/services/core/java/com/android/server/InputContentUriTokenHandler.java
+++ b/services/core/java/com/android/server/InputContentUriTokenHandler.java
@@ -45,40 +45,48 @@
@GuardedBy("mLock")
private IBinder mPermissionOwnerToken = null;
- static InputContentUriTokenHandler create(@NonNull Uri contentUri, int sourceUid,
+ InputContentUriTokenHandler(@NonNull Uri contentUri, int sourceUid,
@NonNull String targetPackage, @UserIdInt int sourceUserId,
@UserIdInt int targetUserId) {
- final IBinder permissionOwner;
- try {
- permissionOwner = ActivityManagerNative.getDefault()
- .newUriPermissionOwner("InputContentUriTokenHandler");
- } catch (RemoteException e) {
- return null;
- }
-
- long origId = Binder.clearCallingIdentity();
- try {
- ActivityManagerNative.getDefault().grantUriPermissionFromOwner(
- permissionOwner, sourceUserId, targetPackage, contentUri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, targetUserId);
- } catch (RemoteException e) {
- return null;
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- return new InputContentUriTokenHandler(contentUri, sourceUid, targetPackage, sourceUserId,
- targetUserId, permissionOwner);
- }
-
- private InputContentUriTokenHandler(@NonNull Uri contentUri, int sourceUid,
- @NonNull String targetPackage, @UserIdInt int sourceUserId,
- @UserIdInt int targetUserId, @NonNull IBinder permissionOwnerToken) {
mUri = contentUri;
mSourceUid = sourceUid;
mTargetPackage = targetPackage;
mSourceUserId = sourceUserId;
mTargetUserId = targetUserId;
- mPermissionOwnerToken = permissionOwnerToken;
+ }
+
+ @Override
+ public void take() {
+ synchronized (mLock) {
+ if (mPermissionOwnerToken != null) {
+ // Permission is already granted.
+ return;
+ }
+
+ try {
+ mPermissionOwnerToken = ActivityManagerNative.getDefault()
+ .newUriPermissionOwner("InputContentUriTokenHandler");
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
+ doTakeLocked(mPermissionOwnerToken);
+ }
+ }
+
+ private void doTakeLocked(@NonNull IBinder permissionOwner) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ try {
+ ActivityManagerNative.getDefault().grantUriPermissionFromOwner(
+ permissionOwner, mSourceUid, mTargetPackage, mUri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId, mTargetUserId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 2c22829..e0d89f2 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3953,7 +3953,7 @@
}
final int imeUserId = UserHandle.getUserId(uid);
final int appUserId = UserHandle.getUserId(mCurClient.uid);
- return InputContentUriTokenHandler.create(contentUri, uid, packageName, imeUserId,
+ return new InputContentUriTokenHandler(contentUri, uid, packageName, imeUserId,
appUserId);
}
}