Merge "Add InputMethodService#exposeContent()" into nyc-mr1-dev
This commit is contained in:
@@ -318,6 +318,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
|
||||
core/java/com/android/internal/backup/IBackupTransport.aidl \
|
||||
core/java/com/android/internal/backup/IObbBackupService.aidl \
|
||||
core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \
|
||||
core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
|
||||
core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
|
||||
core/java/com/android/internal/policy/IKeyguardService.aidl \
|
||||
|
||||
@@ -18857,6 +18857,7 @@ 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();
|
||||
@@ -44922,13 +44923,15 @@ package android.view.inputmethod {
|
||||
method public void setTarget(android.view.inputmethod.InputConnection);
|
||||
}
|
||||
|
||||
public class InputContentInfo implements android.os.Parcelable {
|
||||
public final class InputContentInfo implements android.os.Parcelable {
|
||||
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription);
|
||||
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri);
|
||||
method public int describeContents();
|
||||
method public android.net.Uri getContentUri();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -20057,6 +20057,7 @@ 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();
|
||||
@@ -48029,13 +48030,15 @@ package android.view.inputmethod {
|
||||
method public void setTarget(android.view.inputmethod.InputConnection);
|
||||
}
|
||||
|
||||
public class InputContentInfo implements android.os.Parcelable {
|
||||
public final class InputContentInfo implements android.os.Parcelable {
|
||||
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription);
|
||||
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri);
|
||||
method public int describeContents();
|
||||
method public android.net.Uri getContentUri();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -18871,6 +18871,7 @@ 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();
|
||||
@@ -45002,13 +45003,15 @@ package android.view.inputmethod {
|
||||
method public void setTarget(android.view.inputmethod.InputConnection);
|
||||
}
|
||||
|
||||
public class InputContentInfo implements android.os.Parcelable {
|
||||
public final class InputContentInfo implements android.os.Parcelable {
|
||||
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription);
|
||||
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri);
|
||||
method public int describeContents();
|
||||
method public android.net.Uri getContentUri();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.annotation.CallSuper;
|
||||
import android.annotation.DrawableRes;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
@@ -65,6 +66,7 @@ import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputBinding;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputContentInfo;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
@@ -2597,6 +2599,39 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
return mImm.getInputMethodWindowVisibleHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* <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
|
||||
* 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.
|
||||
*/
|
||||
public final boolean exposeContent(@NonNull InputContentInfo inputContentInfo,
|
||||
@NonNull EditorInfo editorInfo) {
|
||||
if (inputContentInfo == null) {
|
||||
throw new NullPointerException("inputContentInfo");
|
||||
}
|
||||
if (editorInfo == null) {
|
||||
throw new NullPointerException("editorInfo");
|
||||
}
|
||||
|
||||
return mImm.exposeContent(mToken, inputContentInfo, editorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a dump of the InputMethodService's internal state. Override
|
||||
* to add your own information to the dump.
|
||||
|
||||
@@ -22,13 +22,16 @@ import android.content.ClipDescription;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
|
||||
/**
|
||||
* A container object with which input methods can send content files to the target application.
|
||||
*/
|
||||
public class InputContentInfo implements Parcelable {
|
||||
public final class InputContentInfo implements Parcelable {
|
||||
|
||||
@NonNull
|
||||
private final Uri mContentUri;
|
||||
@@ -36,6 +39,8 @@ public class InputContentInfo implements Parcelable {
|
||||
private final ClipDescription mDescription;
|
||||
@Nullable
|
||||
private final Uri mLinkUri;
|
||||
@NonNull
|
||||
private IInputContentUriToken mUriToken;
|
||||
|
||||
/**
|
||||
* Constructs {@link InputContentInfo} object only with mandatory data.
|
||||
@@ -110,7 +115,7 @@ public class InputContentInfo implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
final String contentUriScheme = contentUri.getScheme();
|
||||
if (contentUriScheme == null || !contentUriScheme.equalsIgnoreCase("content")) {
|
||||
if (!"content".equals(contentUriScheme)) {
|
||||
if (throwException) {
|
||||
throw new InvalidParameterException("contentUri must have content scheme");
|
||||
}
|
||||
@@ -137,8 +142,9 @@ public class InputContentInfo implements Parcelable {
|
||||
public Uri getContentUri() { return mContentUri; }
|
||||
|
||||
/**
|
||||
* @return {@link ClipDescription} object that contains the metadata of {@code contentUri} such
|
||||
* as MIME type(s). {@link ClipDescription#getLabel()} can be used for accessibility purpose.
|
||||
* @return {@link ClipDescription} object that contains the metadata of {@code #getContentUri()}
|
||||
* such as MIME type(s). {@link ClipDescription#getLabel()} can be used for accessibility
|
||||
* purpose.
|
||||
*/
|
||||
@NonNull
|
||||
public ClipDescription getDescription() { return mDescription; }
|
||||
@@ -149,6 +155,47 @@ public class InputContentInfo implements Parcelable {
|
||||
@Nullable
|
||||
public Uri getLinkUri() { return mLinkUri; }
|
||||
|
||||
void setUriToken(IInputContentUriToken token) {
|
||||
if (mUriToken != null) {
|
||||
throw new IllegalStateException("URI token is already set");
|
||||
}
|
||||
mUriToken = token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
public void releasePermission() {
|
||||
if (mUriToken == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mUriToken.release();
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
} finally {
|
||||
mUriToken = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to package this object into a {@link Parcel}.
|
||||
*
|
||||
@@ -160,12 +207,23 @@ public class InputContentInfo implements Parcelable {
|
||||
Uri.writeToParcel(dest, mContentUri);
|
||||
mDescription.writeToParcel(dest, flags);
|
||||
Uri.writeToParcel(dest, mLinkUri);
|
||||
if (mUriToken != null) {
|
||||
dest.writeInt(1);
|
||||
dest.writeStrongBinder(mUriToken.asBinder());
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
private InputContentInfo(@NonNull Parcel source) {
|
||||
mContentUri = Uri.CREATOR.createFromParcel(source);
|
||||
mDescription = ClipDescription.CREATOR.createFromParcel(source);
|
||||
mLinkUri = Uri.CREATOR.createFromParcel(source);
|
||||
if (source.readInt() == 1) {
|
||||
mUriToken = IInputContentUriToken.Stub.asInterface(source.readStrongBinder());
|
||||
} else {
|
||||
mUriToken = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.view.inputmethod;
|
||||
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.view.IInputConnectionWrapper;
|
||||
import com.android.internal.view.IInputContext;
|
||||
@@ -30,6 +31,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -56,6 +58,7 @@ import android.view.ViewRootImpl;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -2288,6 +2291,41 @@ public final class InputMethodManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
|
||||
* permission to the content.
|
||||
*
|
||||
* <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo, EditorInfo)}
|
||||
* for details.</p>
|
||||
*
|
||||
* @param token Supplies the identifying token given to an input method when it was started,
|
||||
* which allows it to perform this operation on itself.
|
||||
* @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.
|
||||
* @hide
|
||||
*/
|
||||
public boolean exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
|
||||
@NonNull EditorInfo editorInfo) {
|
||||
final IInputContentUriToken uriToken;
|
||||
final Uri contentUri = inputContentInfo.getContentUri();
|
||||
try {
|
||||
uriToken = mService.createInputContentUriToken(token, contentUri,
|
||||
editorInfo.packageName);
|
||||
if (uriToken == null) {
|
||||
return false;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
|
||||
+ " packageName=" + editorInfo.packageName, e);
|
||||
return false;
|
||||
}
|
||||
inputContentInfo.setUriToken(uriToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
|
||||
final Printer p = new PrintWriterPrinter(fout);
|
||||
p.println("Input method client state for " + this + ":");
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
** Copyright 2016, 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.internal.inputmethod;
|
||||
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
interface IInputContentUriToken {
|
||||
void take();
|
||||
void release();
|
||||
}
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package com.android.internal.view;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.ResultReceiver;
|
||||
import android.text.style.SuggestionSpan;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
import com.android.internal.view.InputBindResult;
|
||||
import com.android.internal.view.IInputContext;
|
||||
import com.android.internal.view.IInputMethodClient;
|
||||
@@ -81,5 +83,8 @@ interface IInputMethodManager {
|
||||
int getInputMethodWindowVisibleHeight();
|
||||
void clearLastInputMethodWindowForTransition(in IBinder token);
|
||||
|
||||
IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri,
|
||||
in String packageName);
|
||||
|
||||
oneway void notifyUserAction(int sequenceNumber);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
** Copyright 2016, 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.server;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
|
||||
final class InputContentUriTokenHandler extends IInputContentUriToken.Stub {
|
||||
|
||||
@NonNull
|
||||
private final Uri mUri;
|
||||
private final int mSourceUid;
|
||||
@NonNull
|
||||
private final String mTargetPackage;
|
||||
@UserIdInt
|
||||
private final int mSourceUserId;
|
||||
@UserIdInt
|
||||
private final int mTargetUserId;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private IBinder mPermissionOwnerToken = null;
|
||||
|
||||
InputContentUriTokenHandler(@NonNull Uri contentUri, int sourceUid,
|
||||
@NonNull String targetPackage, @UserIdInt int sourceUserId,
|
||||
@UserIdInt int targetUserId) {
|
||||
mUri = contentUri;
|
||||
mSourceUid = sourceUid;
|
||||
mTargetPackage = targetPackage;
|
||||
mSourceUserId = sourceUserId;
|
||||
mTargetUserId = targetUserId;
|
||||
}
|
||||
|
||||
@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
|
||||
public void release() {
|
||||
synchronized (mLock) {
|
||||
if (mPermissionOwnerToken == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ActivityManagerNative.getDefault().revokeUriPermissionFromOwner(
|
||||
mPermissionOwnerToken, mUri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
} finally {
|
||||
mPermissionOwnerToken = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
release();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.android.server;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
|
||||
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
|
||||
import com.android.internal.inputmethod.InputMethodUtils;
|
||||
@@ -137,6 +138,7 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -3910,6 +3912,52 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
|
||||
@Nullable Uri contentUri, @Nullable String packageName) {
|
||||
if (!calledFromValidUser()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (token == null) {
|
||||
throw new NullPointerException("token");
|
||||
}
|
||||
if (packageName == null) {
|
||||
throw new NullPointerException("packageName");
|
||||
}
|
||||
if (contentUri == null) {
|
||||
throw new NullPointerException("contentUri");
|
||||
}
|
||||
final String contentUriScheme = contentUri.getScheme();
|
||||
if (!"content".equals(contentUriScheme)) {
|
||||
throw new InvalidParameterException("contentUri must have content scheme");
|
||||
}
|
||||
|
||||
synchronized (mMethodMap) {
|
||||
final int uid = Binder.getCallingUid();
|
||||
if (mCurMethodId == null) {
|
||||
return null;
|
||||
}
|
||||
if (mCurToken != token) {
|
||||
Slog.e(TAG, "Ignoring createInputContentUriToken mCurToken=" + mCurToken
|
||||
+ " token=" + token);
|
||||
return null;
|
||||
}
|
||||
// We cannot simply distinguish a bad IME that reports an arbitrary package name from
|
||||
// an unfortunate IME whose internal state is already obsolete due to the asynchronous
|
||||
// nature of our system. Let's compare it with our internal record.
|
||||
if (!TextUtils.equals(mCurAttribute.packageName, packageName)) {
|
||||
Slog.e(TAG, "Ignoring createInputContentUriToken mCurAttribute.packageName="
|
||||
+ mCurAttribute.packageName + " packageName=" + packageName);
|
||||
return null;
|
||||
}
|
||||
final int imeUserId = UserHandle.getUserId(uid);
|
||||
final int appUserId = UserHandle.getUserId(mCurClient.uid);
|
||||
return new InputContentUriTokenHandler(contentUri, uid, packageName, imeUserId,
|
||||
appUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package com.android.layoutlib.bridge.android;
|
||||
|
||||
import com.android.internal.inputmethod.IInputContentUriToken;
|
||||
import com.android.internal.view.IInputContext;
|
||||
import com.android.internal.view.IInputMethodClient;
|
||||
import com.android.internal.view.IInputMethodManager;
|
||||
import com.android.internal.view.InputBindResult;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
@@ -239,4 +241,11 @@ public class BridgeIInputMethodManager implements IInputMethodManager {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IInputContentUriToken createInputContentUriToken(IBinder token, Uri contentUri,
|
||||
String packageName) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user