Loading core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -28,7 +28,7 @@ import android.view.SurfaceControlViewHost; oneway interface IInlineSuggestionUiCallback { oneway interface IInlineSuggestionUiCallback { void onClick(); void onClick(); void onLongClick(); void onLongClick(); void onContent(in SurfaceControlViewHost.SurfacePackage surface); void onContent(in SurfaceControlViewHost.SurfacePackage surface, int width, int height); void onError(); void onError(); void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId); void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId); void onStartIntentSender(in IntentSender intentSender); void onStartIntentSender(in IntentSender intentSender); Loading core/java/android/service/autofill/InlineSuggestionRenderService.java +66 −21 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.TestApi; import android.app.Service; import android.app.Service; import android.app.slice.Slice; import android.content.Intent; import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender; import android.graphics.PixelFormat; import android.graphics.PixelFormat; Loading @@ -34,14 +33,15 @@ import android.os.Looper; import android.os.RemoteCallback; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.util.Log; import android.util.Size; import android.view.Display; import android.view.Display; import android.view.SurfaceControlViewHost; import android.view.SurfaceControlViewHost; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager; /** /** * A service that renders an inline presentation given the {@link InlinePresentation} containing * A service that renders an inline presentation view given the {@link InlinePresentation}. * a {@link Slice} built using the {@link androidx.autofill.AutofillSliceBuilder}. * * * {@hide} * {@hide} */ */ Loading @@ -55,8 +55,8 @@ public abstract class InlineSuggestionRenderService extends Service { * The {@link Intent} that must be declared as handled by the service. * The {@link Intent} that must be declared as handled by the service. * * * <p>To be supported, the service must also require the * <p>To be supported, the service must also require the * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so that * that other applications can not abuse it. * other applications can not abuse it. */ */ public static final String SERVICE_INTERFACE = public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService"; "android.service.autofill.InlineSuggestionRenderService"; Loading @@ -65,6 +65,45 @@ public abstract class InlineSuggestionRenderService extends Service { private IInlineSuggestionUiCallback mCallback; private IInlineSuggestionUiCallback mCallback; /** * If the specified {@code width}/{@code height} is an exact value, then it will be returned as * is, otherwise the method tries to measure a size that is just large enough to fit the view * content, within constraints posed by {@code minSize} and {@code maxSize}. * * @param view the view for which we measure the size * @param width the expected width of the view, either an exact value or {@link * ViewGroup.LayoutParams#WRAP_CONTENT} * @param height the expected width of the view, either an exact value or {@link * ViewGroup.LayoutParams#WRAP_CONTENT} * @param minSize the lower bound of the size to be returned * @param maxSize the upper bound of the size to be returned * @return the measured size of the view based on the given size constraints. */ private Size measuredSize(@NonNull View view, int width, int height, @NonNull Size minSize, @NonNull Size maxSize) { if (width != ViewGroup.LayoutParams.WRAP_CONTENT && height != ViewGroup.LayoutParams.WRAP_CONTENT) { return new Size(width, height); } int widthMeasureSpec; if (width == ViewGroup.LayoutParams.WRAP_CONTENT) { widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize.getWidth(), View.MeasureSpec.AT_MOST); } else { widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY); } int heightMeasureSpec; if (height == ViewGroup.LayoutParams.WRAP_CONTENT) { heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize.getHeight(), View.MeasureSpec.AT_MOST); } else { heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); } view.measure(widthMeasureSpec, heightMeasureSpec); return new Size(Math.max(view.getMeasuredWidth(), minSize.getWidth()), Math.max(view.getMeasuredHeight(), minSize.getHeight())); } private void handleRenderSuggestion(IInlineSuggestionUiCallback callback, private void handleRenderSuggestion(IInlineSuggestionUiCallback callback, InlinePresentation presentation, int width, int height, IBinder hostInputToken, InlinePresentation presentation, int width, int height, IBinder hostInputToken, int displayId) { int displayId) { Loading @@ -82,6 +121,7 @@ public abstract class InlineSuggestionRenderService extends Service { try { try { final View suggestionView = onRenderSuggestion(presentation, width, height); final View suggestionView = onRenderSuggestion(presentation, width, height); if (suggestionView == null) { if (suggestionView == null) { Log.w(TAG, "ExtServices failed to render the inline suggestion view."); try { try { callback.onError(); callback.onError(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -90,12 +130,15 @@ public abstract class InlineSuggestionRenderService extends Service { return; return; } } mCallback = callback; mCallback = callback; final Size measuredSize = measuredSize(suggestionView, width, height, presentation.getInlinePresentationSpec().getMinSize(), presentation.getInlinePresentationSpec().getMaxSize()); Log.v(TAG, "width=" + width + ", height=" + height + ", measuredSize=" + measuredSize); final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback); final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback); suggestionRoot.addView(suggestionView); suggestionRoot.addView(suggestionView); WindowManager.LayoutParams lp = WindowManager.LayoutParams lp = new WindowManager.LayoutParams(measuredSize.getWidth(), new WindowManager.LayoutParams(width, height, measuredSize.getHeight(), WindowManager.LayoutParams.TYPE_APPLICATION, 0, WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT); PixelFormat.TRANSPARENT); final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(), final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(), Loading Loading @@ -124,7 +167,8 @@ public abstract class InlineSuggestionRenderService extends Service { return true; return true; }); }); sendResult(callback, host.getSurfacePackage()); sendResult(callback, host.getSurfacePackage(), measuredSize.getWidth(), measuredSize.getHeight()); } finally { } finally { updateDisplay(Display.DEFAULT_DISPLAY); updateDisplay(Display.DEFAULT_DISPLAY); } } Loading @@ -136,9 +180,9 @@ public abstract class InlineSuggestionRenderService extends Service { } } private void sendResult(@NonNull IInlineSuggestionUiCallback callback, private void sendResult(@NonNull IInlineSuggestionUiCallback callback, @Nullable SurfaceControlViewHost.SurfacePackage surface) { @Nullable SurfaceControlViewHost.SurfacePackage surface, int width, int height) { try { try { callback.onContent(surface); callback.onContent(surface, width, height); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "RemoteException calling onContent(" + surface + ")"); Log.w(TAG, "RemoteException calling onContent(" + surface + ")"); } } Loading @@ -154,8 +198,8 @@ public abstract class InlineSuggestionRenderService extends Service { public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback, public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback, @NonNull InlinePresentation presentation, int width, int height, @NonNull InlinePresentation presentation, int width, int height, @Nullable IBinder hostInputToken, int displayId) { @Nullable IBinder hostInputToken, int displayId) { mHandler.sendMessage(obtainMessage( mHandler.sendMessage( InlineSuggestionRenderService::handleRenderSuggestion, obtainMessage(InlineSuggestionRenderService::handleRenderSuggestion, InlineSuggestionRenderService.this, callback, presentation, InlineSuggestionRenderService.this, callback, presentation, width, height, hostInputToken, displayId)); width, height, hostInputToken, displayId)); } } Loading @@ -176,7 +220,8 @@ public abstract class InlineSuggestionRenderService extends Service { /** /** * Starts the {@link IntentSender} from the client app. * Starts the {@link IntentSender} from the client app. * * * @param intentSender the {@link IntentSender} to start the attribution UI from the client app. * @param intentSender the {@link IntentSender} to start the attribution UI from the client * app. */ */ public final void startIntentSender(@NonNull IntentSender intentSender) { public final void startIntentSender(@NonNull IntentSender intentSender) { if (mCallback == null) return; if (mCallback == null) return; Loading @@ -200,8 +245,8 @@ public abstract class InlineSuggestionRenderService extends Service { * Renders the slice into a view. * Renders the slice into a view. */ */ @Nullable @Nullable public View onRenderSuggestion(@NonNull InlinePresentation presentation, public View onRenderSuggestion(@NonNull InlinePresentation presentation, int width, int width, int height) { int height) { Log.e(TAG, "service implementation (" + getClass() + " does not implement " Log.e(TAG, "service implementation (" + getClass() + " does not implement " + "onRenderSuggestion()"); + "onRenderSuggestion()"); return null; return null; Loading core/java/android/view/inputmethod/InlineSuggestion.java +38 −15 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.os.RemoteException; import android.util.Size; import android.util.Size; import android.util.Slog; import android.util.Slog; import android.view.SurfaceControlViewHost; import android.view.SurfaceControlViewHost; import android.view.ViewGroup; import android.widget.inline.InlineContentView; import android.widget.inline.InlineContentView; import com.android.internal.util.DataClass; import com.android.internal.util.DataClass; Loading Loading @@ -94,19 +95,26 @@ public final class InlineSuggestion implements Parcelable { /** /** * Inflates a view with the content of this suggestion at a specific size. * Inflates a view with the content of this suggestion at a specific size. * The size must be between the * * <p> The size must be either 1) between the * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()}. * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()}, * or 2) {@link ViewGroup.LayoutParams#WRAP_CONTENT}. If the size is set to * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, then the size of the inflated view will be just * large enough to fit the content, while still conforming to the min / max size specified by * the {@link android.widget.inline.InlinePresentationSpec}. * * * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an * {@link android.view.View.OnLongClickListener} to the view in the * {@link android.view.View.OnLongClickListener} to the view in the * {@code callback} to receive click and * {@code callback} to receive click and long click events on the view. * long click events on the view. * * * @param context Context in which to inflate the view. * @param context Context in which to inflate the view. * @param size The size at which to inflate the suggestion. * @param size The size at which to inflate the suggestion. For each dimension, it maybe * @param callback Callback for receiving the inflated view. * an exact value or {@link ViewGroup.LayoutParams#WRAP_CONTENT}. * @param callback Callback for receiving the inflated view, where the * {@link ViewGroup.LayoutParams} of the view is set as the actual size of * the underlying remote view. * @throws IllegalArgumentException If an invalid argument is passed. * @throws IllegalArgumentException If an invalid argument is passed. * @throws IllegalStateException If this method is already called. * @throws IllegalStateException If this method is already called. */ */ Loading @@ -115,10 +123,11 @@ public final class InlineSuggestion implements Parcelable { @NonNull Consumer<InlineContentView> callback) { @NonNull Consumer<InlineContentView> callback) { final Size minSize = mInfo.getInlinePresentationSpec().getMinSize(); final Size minSize = mInfo.getInlinePresentationSpec().getMinSize(); final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize(); final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize(); if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight() if (!isValid(size.getWidth(), minSize.getWidth(), maxSize.getWidth()) || size.getWidth() < minSize.getWidth() || size.getWidth() > maxSize.getWidth()) { || !isValid(size.getHeight(), minSize.getHeight(), maxSize.getHeight())) { throw new IllegalArgumentException("size not between min:" throw new IllegalArgumentException( + minSize + " and max:" + maxSize); "size is neither between min:" + minSize + " and max:" + maxSize + ", nor wrap_content"); } } mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback); mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback); AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { Loading @@ -136,6 +145,17 @@ public final class InlineSuggestion implements Parcelable { }); }); } } /** * Returns true if the {@code actual} length is within [min, max] or is {@link * ViewGroup.LayoutParams#WRAP_CONTENT}. */ private static boolean isValid(int actual, int min, int max) { if (actual == ViewGroup.LayoutParams.WRAP_CONTENT) { return true; } return actual >= min && actual <= max; } private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context, private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context, Executor callbackExecutor, Consumer<InlineContentView> callback) { Executor callbackExecutor, Consumer<InlineContentView> callback) { if (mInlineContentCallback != null) { if (mInlineContentCallback != null) { Loading @@ -154,10 +174,11 @@ public final class InlineSuggestion implements Parcelable { @Override @Override @BinderThread @BinderThread public void onContent(SurfaceControlViewHost.SurfacePackage content) { public void onContent(SurfaceControlViewHost.SurfacePackage content, int width, int height) { final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); if (callbackImpl != null) { if (callbackImpl != null) { callbackImpl.onContent(content); callbackImpl.onContent(content, width, height); } } } } Loading Loading @@ -196,11 +217,13 @@ public final class InlineSuggestion implements Parcelable { } } @BinderThread @BinderThread public void onContent(SurfaceControlViewHost.SurfacePackage content) { public void onContent(SurfaceControlViewHost.SurfacePackage content, int width, int height) { if (content == null) { if (content == null) { mCallbackExecutor.execute(() -> mCallback.accept(/* view */null)); mCallbackExecutor.execute(() -> mCallback.accept(/* view */null)); } else { } else { mView = new InlineContentView(mContext); mView = new InlineContentView(mContext); mView.setLayoutParams(new ViewGroup.LayoutParams(width, height)); mView.setChildSurfacePackage(content); mView.setChildSurfacePackage(content); mCallbackExecutor.execute(() -> mCallback.accept(mView)); mCallbackExecutor.execute(() -> mCallback.accept(mView)); } } Loading Loading @@ -398,10 +421,10 @@ public final class InlineSuggestion implements Parcelable { }; }; @DataClass.Generated( @DataClass.Generated( time = 1585180783541L, time = 1587771173367L, codegenVersion = "1.0.15", codegenVersion = "1.0.15", sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java", sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java", inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)") inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate static boolean isValid(int,int,int)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)") @Deprecated @Deprecated private void __metadata() {} private void __metadata() {} Loading core/java/com/android/internal/view/inline/IInlineContentCallback.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -23,7 +23,7 @@ import android.view.SurfaceControlViewHost; * {@hide} * {@hide} */ */ oneway interface IInlineContentCallback { oneway interface IInlineContentCallback { void onContent(in SurfaceControlViewHost.SurfacePackage content); void onContent(in SurfaceControlViewHost.SurfacePackage content, int width, int height); void onClick(); void onClick(); void onLongClick(); void onLongClick(); } } services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java +3 −2 Original line number Original line Diff line number Diff line Loading @@ -319,9 +319,10 @@ public final class InlineSuggestionFactory { } } @Override @Override public void onContent(SurfaceControlViewHost.SurfacePackage surface) public void onContent(SurfaceControlViewHost.SurfacePackage surface, int width, int height) throws RemoteException { throws RemoteException { callback.onContent(surface); callback.onContent(surface, width, height); surface.release(); surface.release(); } } Loading Loading
core/java/android/service/autofill/IInlineSuggestionUiCallback.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -28,7 +28,7 @@ import android.view.SurfaceControlViewHost; oneway interface IInlineSuggestionUiCallback { oneway interface IInlineSuggestionUiCallback { void onClick(); void onClick(); void onLongClick(); void onLongClick(); void onContent(in SurfaceControlViewHost.SurfacePackage surface); void onContent(in SurfaceControlViewHost.SurfacePackage surface, int width, int height); void onError(); void onError(); void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId); void onTransferTouchFocusToImeWindow(in IBinder sourceInputToken, int displayId); void onStartIntentSender(in IntentSender intentSender); void onStartIntentSender(in IntentSender intentSender); Loading
core/java/android/service/autofill/InlineSuggestionRenderService.java +66 −21 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.TestApi; import android.app.Service; import android.app.Service; import android.app.slice.Slice; import android.content.Intent; import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender; import android.graphics.PixelFormat; import android.graphics.PixelFormat; Loading @@ -34,14 +33,15 @@ import android.os.Looper; import android.os.RemoteCallback; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.RemoteException; import android.util.Log; import android.util.Log; import android.util.Size; import android.view.Display; import android.view.Display; import android.view.SurfaceControlViewHost; import android.view.SurfaceControlViewHost; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager; /** /** * A service that renders an inline presentation given the {@link InlinePresentation} containing * A service that renders an inline presentation view given the {@link InlinePresentation}. * a {@link Slice} built using the {@link androidx.autofill.AutofillSliceBuilder}. * * * {@hide} * {@hide} */ */ Loading @@ -55,8 +55,8 @@ public abstract class InlineSuggestionRenderService extends Service { * The {@link Intent} that must be declared as handled by the service. * The {@link Intent} that must be declared as handled by the service. * * * <p>To be supported, the service must also require the * <p>To be supported, the service must also require the * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so * {@link android.Manifest.permission#BIND_INLINE_SUGGESTION_RENDER_SERVICE} permission so that * that other applications can not abuse it. * other applications can not abuse it. */ */ public static final String SERVICE_INTERFACE = public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService"; "android.service.autofill.InlineSuggestionRenderService"; Loading @@ -65,6 +65,45 @@ public abstract class InlineSuggestionRenderService extends Service { private IInlineSuggestionUiCallback mCallback; private IInlineSuggestionUiCallback mCallback; /** * If the specified {@code width}/{@code height} is an exact value, then it will be returned as * is, otherwise the method tries to measure a size that is just large enough to fit the view * content, within constraints posed by {@code minSize} and {@code maxSize}. * * @param view the view for which we measure the size * @param width the expected width of the view, either an exact value or {@link * ViewGroup.LayoutParams#WRAP_CONTENT} * @param height the expected width of the view, either an exact value or {@link * ViewGroup.LayoutParams#WRAP_CONTENT} * @param minSize the lower bound of the size to be returned * @param maxSize the upper bound of the size to be returned * @return the measured size of the view based on the given size constraints. */ private Size measuredSize(@NonNull View view, int width, int height, @NonNull Size minSize, @NonNull Size maxSize) { if (width != ViewGroup.LayoutParams.WRAP_CONTENT && height != ViewGroup.LayoutParams.WRAP_CONTENT) { return new Size(width, height); } int widthMeasureSpec; if (width == ViewGroup.LayoutParams.WRAP_CONTENT) { widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize.getWidth(), View.MeasureSpec.AT_MOST); } else { widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY); } int heightMeasureSpec; if (height == ViewGroup.LayoutParams.WRAP_CONTENT) { heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxSize.getHeight(), View.MeasureSpec.AT_MOST); } else { heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); } view.measure(widthMeasureSpec, heightMeasureSpec); return new Size(Math.max(view.getMeasuredWidth(), minSize.getWidth()), Math.max(view.getMeasuredHeight(), minSize.getHeight())); } private void handleRenderSuggestion(IInlineSuggestionUiCallback callback, private void handleRenderSuggestion(IInlineSuggestionUiCallback callback, InlinePresentation presentation, int width, int height, IBinder hostInputToken, InlinePresentation presentation, int width, int height, IBinder hostInputToken, int displayId) { int displayId) { Loading @@ -82,6 +121,7 @@ public abstract class InlineSuggestionRenderService extends Service { try { try { final View suggestionView = onRenderSuggestion(presentation, width, height); final View suggestionView = onRenderSuggestion(presentation, width, height); if (suggestionView == null) { if (suggestionView == null) { Log.w(TAG, "ExtServices failed to render the inline suggestion view."); try { try { callback.onError(); callback.onError(); } catch (RemoteException e) { } catch (RemoteException e) { Loading @@ -90,12 +130,15 @@ public abstract class InlineSuggestionRenderService extends Service { return; return; } } mCallback = callback; mCallback = callback; final Size measuredSize = measuredSize(suggestionView, width, height, presentation.getInlinePresentationSpec().getMinSize(), presentation.getInlinePresentationSpec().getMaxSize()); Log.v(TAG, "width=" + width + ", height=" + height + ", measuredSize=" + measuredSize); final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback); final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback); suggestionRoot.addView(suggestionView); suggestionRoot.addView(suggestionView); WindowManager.LayoutParams lp = WindowManager.LayoutParams lp = new WindowManager.LayoutParams(measuredSize.getWidth(), new WindowManager.LayoutParams(width, height, measuredSize.getHeight(), WindowManager.LayoutParams.TYPE_APPLICATION, 0, WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT); PixelFormat.TRANSPARENT); final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(), final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(), Loading Loading @@ -124,7 +167,8 @@ public abstract class InlineSuggestionRenderService extends Service { return true; return true; }); }); sendResult(callback, host.getSurfacePackage()); sendResult(callback, host.getSurfacePackage(), measuredSize.getWidth(), measuredSize.getHeight()); } finally { } finally { updateDisplay(Display.DEFAULT_DISPLAY); updateDisplay(Display.DEFAULT_DISPLAY); } } Loading @@ -136,9 +180,9 @@ public abstract class InlineSuggestionRenderService extends Service { } } private void sendResult(@NonNull IInlineSuggestionUiCallback callback, private void sendResult(@NonNull IInlineSuggestionUiCallback callback, @Nullable SurfaceControlViewHost.SurfacePackage surface) { @Nullable SurfaceControlViewHost.SurfacePackage surface, int width, int height) { try { try { callback.onContent(surface); callback.onContent(surface, width, height); } catch (RemoteException e) { } catch (RemoteException e) { Log.w(TAG, "RemoteException calling onContent(" + surface + ")"); Log.w(TAG, "RemoteException calling onContent(" + surface + ")"); } } Loading @@ -154,8 +198,8 @@ public abstract class InlineSuggestionRenderService extends Service { public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback, public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback, @NonNull InlinePresentation presentation, int width, int height, @NonNull InlinePresentation presentation, int width, int height, @Nullable IBinder hostInputToken, int displayId) { @Nullable IBinder hostInputToken, int displayId) { mHandler.sendMessage(obtainMessage( mHandler.sendMessage( InlineSuggestionRenderService::handleRenderSuggestion, obtainMessage(InlineSuggestionRenderService::handleRenderSuggestion, InlineSuggestionRenderService.this, callback, presentation, InlineSuggestionRenderService.this, callback, presentation, width, height, hostInputToken, displayId)); width, height, hostInputToken, displayId)); } } Loading @@ -176,7 +220,8 @@ public abstract class InlineSuggestionRenderService extends Service { /** /** * Starts the {@link IntentSender} from the client app. * Starts the {@link IntentSender} from the client app. * * * @param intentSender the {@link IntentSender} to start the attribution UI from the client app. * @param intentSender the {@link IntentSender} to start the attribution UI from the client * app. */ */ public final void startIntentSender(@NonNull IntentSender intentSender) { public final void startIntentSender(@NonNull IntentSender intentSender) { if (mCallback == null) return; if (mCallback == null) return; Loading @@ -200,8 +245,8 @@ public abstract class InlineSuggestionRenderService extends Service { * Renders the slice into a view. * Renders the slice into a view. */ */ @Nullable @Nullable public View onRenderSuggestion(@NonNull InlinePresentation presentation, public View onRenderSuggestion(@NonNull InlinePresentation presentation, int width, int width, int height) { int height) { Log.e(TAG, "service implementation (" + getClass() + " does not implement " Log.e(TAG, "service implementation (" + getClass() + " does not implement " + "onRenderSuggestion()"); + "onRenderSuggestion()"); return null; return null; Loading
core/java/android/view/inputmethod/InlineSuggestion.java +38 −15 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.os.RemoteException; import android.util.Size; import android.util.Size; import android.util.Slog; import android.util.Slog; import android.view.SurfaceControlViewHost; import android.view.SurfaceControlViewHost; import android.view.ViewGroup; import android.widget.inline.InlineContentView; import android.widget.inline.InlineContentView; import com.android.internal.util.DataClass; import com.android.internal.util.DataClass; Loading Loading @@ -94,19 +95,26 @@ public final class InlineSuggestion implements Parcelable { /** /** * Inflates a view with the content of this suggestion at a specific size. * Inflates a view with the content of this suggestion at a specific size. * The size must be between the * * <p> The size must be either 1) between the * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the * {@link android.widget.inline.InlinePresentationSpec#getMinSize() min size} and the * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the * {@link android.widget.inline.InlinePresentationSpec#getMaxSize() max size} of the * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()}. * presentation spec returned by {@link InlineSuggestionInfo#getInlinePresentationSpec()}, * or 2) {@link ViewGroup.LayoutParams#WRAP_CONTENT}. If the size is set to * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, then the size of the inflated view will be just * large enough to fit the content, while still conforming to the min / max size specified by * the {@link android.widget.inline.InlinePresentationSpec}. * * * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an * {@link android.view.View.OnLongClickListener} to the view in the * {@link android.view.View.OnLongClickListener} to the view in the * {@code callback} to receive click and * {@code callback} to receive click and long click events on the view. * long click events on the view. * * * @param context Context in which to inflate the view. * @param context Context in which to inflate the view. * @param size The size at which to inflate the suggestion. * @param size The size at which to inflate the suggestion. For each dimension, it maybe * @param callback Callback for receiving the inflated view. * an exact value or {@link ViewGroup.LayoutParams#WRAP_CONTENT}. * @param callback Callback for receiving the inflated view, where the * {@link ViewGroup.LayoutParams} of the view is set as the actual size of * the underlying remote view. * @throws IllegalArgumentException If an invalid argument is passed. * @throws IllegalArgumentException If an invalid argument is passed. * @throws IllegalStateException If this method is already called. * @throws IllegalStateException If this method is already called. */ */ Loading @@ -115,10 +123,11 @@ public final class InlineSuggestion implements Parcelable { @NonNull Consumer<InlineContentView> callback) { @NonNull Consumer<InlineContentView> callback) { final Size minSize = mInfo.getInlinePresentationSpec().getMinSize(); final Size minSize = mInfo.getInlinePresentationSpec().getMinSize(); final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize(); final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize(); if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight() if (!isValid(size.getWidth(), minSize.getWidth(), maxSize.getWidth()) || size.getWidth() < minSize.getWidth() || size.getWidth() > maxSize.getWidth()) { || !isValid(size.getHeight(), minSize.getHeight(), maxSize.getHeight())) { throw new IllegalArgumentException("size not between min:" throw new IllegalArgumentException( + minSize + " and max:" + maxSize); "size is neither between min:" + minSize + " and max:" + maxSize + ", nor wrap_content"); } } mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback); mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback); AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { Loading @@ -136,6 +145,17 @@ public final class InlineSuggestion implements Parcelable { }); }); } } /** * Returns true if the {@code actual} length is within [min, max] or is {@link * ViewGroup.LayoutParams#WRAP_CONTENT}. */ private static boolean isValid(int actual, int min, int max) { if (actual == ViewGroup.LayoutParams.WRAP_CONTENT) { return true; } return actual >= min && actual <= max; } private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context, private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context, Executor callbackExecutor, Consumer<InlineContentView> callback) { Executor callbackExecutor, Consumer<InlineContentView> callback) { if (mInlineContentCallback != null) { if (mInlineContentCallback != null) { Loading @@ -154,10 +174,11 @@ public final class InlineSuggestion implements Parcelable { @Override @Override @BinderThread @BinderThread public void onContent(SurfaceControlViewHost.SurfacePackage content) { public void onContent(SurfaceControlViewHost.SurfacePackage content, int width, int height) { final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); if (callbackImpl != null) { if (callbackImpl != null) { callbackImpl.onContent(content); callbackImpl.onContent(content, width, height); } } } } Loading Loading @@ -196,11 +217,13 @@ public final class InlineSuggestion implements Parcelable { } } @BinderThread @BinderThread public void onContent(SurfaceControlViewHost.SurfacePackage content) { public void onContent(SurfaceControlViewHost.SurfacePackage content, int width, int height) { if (content == null) { if (content == null) { mCallbackExecutor.execute(() -> mCallback.accept(/* view */null)); mCallbackExecutor.execute(() -> mCallback.accept(/* view */null)); } else { } else { mView = new InlineContentView(mContext); mView = new InlineContentView(mContext); mView.setLayoutParams(new ViewGroup.LayoutParams(width, height)); mView.setChildSurfacePackage(content); mView.setChildSurfacePackage(content); mCallbackExecutor.execute(() -> mCallback.accept(mView)); mCallbackExecutor.execute(() -> mCallback.accept(mView)); } } Loading Loading @@ -398,10 +421,10 @@ public final class InlineSuggestion implements Parcelable { }; }; @DataClass.Generated( @DataClass.Generated( time = 1585180783541L, time = 1587771173367L, codegenVersion = "1.0.15", codegenVersion = "1.0.15", sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java", sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java", inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)") inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate static boolean isValid(int,int,int)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)") @Deprecated @Deprecated private void __metadata() {} private void __metadata() {} Loading
core/java/com/android/internal/view/inline/IInlineContentCallback.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -23,7 +23,7 @@ import android.view.SurfaceControlViewHost; * {@hide} * {@hide} */ */ oneway interface IInlineContentCallback { oneway interface IInlineContentCallback { void onContent(in SurfaceControlViewHost.SurfacePackage content); void onContent(in SurfaceControlViewHost.SurfacePackage content, int width, int height); void onClick(); void onClick(); void onLongClick(); void onLongClick(); } }
services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java +3 −2 Original line number Original line Diff line number Diff line Loading @@ -319,9 +319,10 @@ public final class InlineSuggestionFactory { } } @Override @Override public void onContent(SurfaceControlViewHost.SurfacePackage surface) public void onContent(SurfaceControlViewHost.SurfacePackage surface, int width, int height) throws RemoteException { throws RemoteException { callback.onContent(surface); callback.onContent(surface, width, height); surface.release(); surface.release(); } } Loading