1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.inputmethod; 18 19 import android.annotation.BinderThread; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.MainThread; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.TestApi; 25 import android.content.Context; 26 import android.os.Handler; 27 import android.os.Looper; 28 import android.os.Parcel; 29 import android.os.Parcelable; 30 import android.os.RemoteException; 31 import android.util.Size; 32 import android.util.Slog; 33 import android.view.SurfaceControlViewHost; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.widget.inline.InlineContentView; 37 38 import com.android.internal.util.DataClass; 39 import com.android.internal.util.Parcelling; 40 import com.android.internal.view.inline.IInlineContentCallback; 41 import com.android.internal.view.inline.IInlineContentProvider; 42 import com.android.internal.view.inline.InlineTooltipUi; 43 44 import java.lang.ref.WeakReference; 45 import java.util.concurrent.Executor; 46 import java.util.function.Consumer; 47 48 /** 49 * This class represents an inline suggestion which is made by one app and can be embedded into the 50 * UI of another. Suggestions may contain sensitive information not known to the host app which 51 * needs to be protected from spoofing. To address that the suggestion view inflated on demand for 52 * embedding is created in such a way that the hosting app cannot introspect its content and cannot 53 * interact with it. 54 */ 55 @DataClass(genEqualsHashCode = true, genToString = true, genHiddenConstDefs = true, 56 genHiddenConstructor = true) 57 public final class InlineSuggestion implements Parcelable { 58 59 private static final String TAG = "InlineSuggestion"; 60 61 @NonNull 62 private final InlineSuggestionInfo mInfo; 63 64 /** 65 * @hide 66 */ 67 @Nullable 68 private final IInlineContentProvider mContentProvider; 69 70 /** 71 * Used to keep a strong reference to the callback so it doesn't get garbage collected. 72 * 73 * @hide 74 */ 75 @DataClass.ParcelWith(InlineContentCallbackImplParceling.class) 76 @Nullable 77 private InlineContentCallbackImpl mInlineContentCallback; 78 79 /** 80 * Used to show up the inline suggestion tooltip. 81 * 82 * @hide 83 */ 84 @Nullable 85 @DataClass.ParcelWith(InlineTooltipUiParceling.class) 86 private InlineTooltipUi mInlineTooltipUi; 87 88 /** 89 * Creates a new {@link InlineSuggestion}, for testing purpose. 90 * 91 * @hide 92 */ 93 @TestApi 94 @NonNull newInlineSuggestion(@onNull InlineSuggestionInfo info)95 public static InlineSuggestion newInlineSuggestion(@NonNull InlineSuggestionInfo info) { 96 return new InlineSuggestion(info, null, /* inlineContentCallback */ null, 97 /* inlineTooltipUi */ null); 98 } 99 100 /** 101 * Creates a new {@link InlineSuggestion}. 102 * 103 * @hide 104 */ InlineSuggestion(@onNull InlineSuggestionInfo info, @Nullable IInlineContentProvider contentProvider)105 public InlineSuggestion(@NonNull InlineSuggestionInfo info, 106 @Nullable IInlineContentProvider contentProvider) { 107 this(info, contentProvider, /* inlineContentCallback */ null, /* inlineTooltipUi */ null); 108 } 109 110 /** 111 * Inflates a view with the content of this suggestion at a specific size. 112 * 113 * <p> Each dimension of the size must satisfy one of the following conditions: 114 * 115 * <ol> 116 * <li>between {@link android.widget.inline.InlinePresentationSpec#getMinSize()} and 117 * {@link android.widget.inline.InlinePresentationSpec#getMaxSize()} of the presentation spec 118 * from {@code mInfo} 119 * <li>{@link ViewGroup.LayoutParams#WRAP_CONTENT} 120 * </ol> 121 * 122 * If the size is set to {@link 123 * ViewGroup.LayoutParams#WRAP_CONTENT}, then the size of the inflated view will be just large 124 * enough to fit the content, while still conforming to the min / max size specified by the 125 * {@link android.widget.inline.InlinePresentationSpec}. 126 * 127 * <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an 128 * {@link android.view.View.OnLongClickListener} to the view in the {@code callback} to receive 129 * click and long click events on the view. 130 * 131 * @param context Context in which to inflate the view. 132 * @param size The size at which to inflate the suggestion. For each dimension, it maybe an 133 * exact value or {@link ViewGroup.LayoutParams#WRAP_CONTENT}. 134 * @param callback Callback for receiving the inflated view, where the {@link 135 * ViewGroup.LayoutParams} of the view is set as the actual size of the 136 * underlying remote view. 137 * @throws IllegalArgumentException If an invalid argument is passed. 138 * @throws IllegalStateException If this method is already called. 139 */ inflate(@onNull Context context, @NonNull Size size, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull Consumer<InlineContentView> callback)140 public void inflate(@NonNull Context context, @NonNull Size size, 141 @NonNull @CallbackExecutor Executor callbackExecutor, 142 @NonNull Consumer<InlineContentView> callback) { 143 final Size minSize = mInfo.getInlinePresentationSpec().getMinSize(); 144 final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize(); 145 if (!isValid(size.getWidth(), minSize.getWidth(), maxSize.getWidth()) 146 || !isValid(size.getHeight(), minSize.getHeight(), maxSize.getHeight())) { 147 throw new IllegalArgumentException( 148 "size is neither between min:" + minSize + " and max:" + maxSize 149 + ", nor wrap_content"); 150 } 151 152 InlineSuggestion toolTip = mInfo.getTooltip(); 153 if (toolTip != null) { 154 if (mInlineTooltipUi == null) { 155 mInlineTooltipUi = new InlineTooltipUi(context); 156 } 157 } else { 158 mInlineTooltipUi = null; 159 } 160 161 mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback, 162 mInlineTooltipUi); 163 if (mContentProvider == null) { 164 callbackExecutor.execute(() -> callback.accept(/* view */ null)); 165 mInlineTooltipUi = null; 166 return; 167 } 168 try { 169 mContentProvider.provideContent(size.getWidth(), size.getHeight(), 170 new InlineContentCallbackWrapper(mInlineContentCallback)); 171 } catch (RemoteException e) { 172 Slog.w(TAG, "Error creating suggestion content surface: " + e); 173 callbackExecutor.execute(() -> callback.accept(/* view */ null)); 174 } 175 if (toolTip == null) return; 176 177 final Size tooltipSize = new Size(ViewGroup.LayoutParams.WRAP_CONTENT, 178 ViewGroup.LayoutParams.WRAP_CONTENT); 179 mInfo.getTooltip().inflate(context, tooltipSize, callbackExecutor, view -> { 180 Handler.getMain().post(() -> mInlineTooltipUi.setTooltipView(view)); 181 }); 182 } 183 184 /** 185 * Returns true if the {@code actual} length is within [min, max] or is {@link 186 * ViewGroup.LayoutParams#WRAP_CONTENT}. 187 */ isValid(int actual, int min, int max)188 private static boolean isValid(int actual, int min, int max) { 189 if (actual == ViewGroup.LayoutParams.WRAP_CONTENT) { 190 return true; 191 } 192 return actual >= min && actual <= max; 193 } 194 getInlineContentCallback(Context context, Executor callbackExecutor, Consumer<InlineContentView> callback, InlineTooltipUi inlineTooltipUi)195 private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context, 196 Executor callbackExecutor, Consumer<InlineContentView> callback, 197 InlineTooltipUi inlineTooltipUi) { 198 if (mInlineContentCallback != null) { 199 throw new IllegalStateException("Already called #inflate()"); 200 } 201 return new InlineContentCallbackImpl(context, mContentProvider, callbackExecutor, 202 callback, inlineTooltipUi); 203 } 204 205 /** 206 * A wrapper class around the {@link InlineContentCallbackImpl} to ensure it's not strongly 207 * reference by the remote system server process. 208 */ 209 private static final class InlineContentCallbackWrapper extends IInlineContentCallback.Stub { 210 211 private final WeakReference<InlineContentCallbackImpl> mCallbackImpl; 212 InlineContentCallbackWrapper(InlineContentCallbackImpl callbackImpl)213 InlineContentCallbackWrapper(InlineContentCallbackImpl callbackImpl) { 214 mCallbackImpl = new WeakReference<>(callbackImpl); 215 } 216 217 @Override 218 @BinderThread onContent(SurfaceControlViewHost.SurfacePackage content, int width, int height)219 public void onContent(SurfaceControlViewHost.SurfacePackage content, int width, 220 int height) { 221 final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); 222 if (callbackImpl != null) { 223 callbackImpl.onContent(content, width, height); 224 } 225 } 226 227 @Override 228 @BinderThread onClick()229 public void onClick() { 230 final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); 231 if (callbackImpl != null) { 232 callbackImpl.onClick(); 233 } 234 } 235 236 @Override 237 @BinderThread onLongClick()238 public void onLongClick() { 239 final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get(); 240 if (callbackImpl != null) { 241 callbackImpl.onLongClick(); 242 } 243 } 244 } 245 246 /** 247 * Handles the communication between the inline suggestion view in current (IME) process and 248 * the remote view provided from the system server. 249 * 250 * <p>This class is thread safe, because all the outside calls are piped into a single 251 * handler thread to be processed. 252 */ 253 private static final class InlineContentCallbackImpl { 254 255 @NonNull 256 private final Handler mMainHandler = new Handler(Looper.getMainLooper()); 257 258 @NonNull 259 private final Context mContext; 260 @Nullable 261 private final IInlineContentProvider mInlineContentProvider; 262 @NonNull 263 private final Executor mCallbackExecutor; 264 265 /** 266 * Callback from the client (IME) that will receive the inflated suggestion view. It'll 267 * only be called once when the view SurfacePackage is first sent back to the client. Any 268 * updates to the view due to attach to window and detach from window events will be 269 * handled under the hood, transparent from the client. 270 */ 271 @NonNull 272 private final Consumer<InlineContentView> mCallback; 273 274 /** 275 * Indicates whether the first content has been received or not. 276 */ 277 private boolean mFirstContentReceived = false; 278 279 /** 280 * The client (IME) side view which internally wraps a remote view. It'll be set when 281 * {@link #onContent(SurfaceControlViewHost.SurfacePackage, int, int)} is called, which 282 * should only happen once in the lifecycle of this inline suggestion instance. 283 */ 284 @Nullable 285 private InlineContentView mView; 286 287 /** 288 * The SurfacePackage pointing to the remote view. It's cached here to be sent to the next 289 * available consumer. 290 */ 291 @Nullable 292 private SurfaceControlViewHost.SurfacePackage mSurfacePackage; 293 294 /** 295 * The callback (from the {@link InlineContentView}) which consumes the surface package. 296 * It's cached here to be called when the SurfacePackage is returned from the remote 297 * view owning process. 298 */ 299 @Nullable 300 private Consumer<SurfaceControlViewHost.SurfacePackage> mSurfacePackageConsumer; 301 302 @Nullable 303 private InlineTooltipUi mInlineTooltipUi; 304 InlineContentCallbackImpl(@onNull Context context, @Nullable IInlineContentProvider inlineContentProvider, @NonNull @CallbackExecutor Executor callbackExecutor, @NonNull Consumer<InlineContentView> callback, @Nullable InlineTooltipUi inlineTooltipUi)305 InlineContentCallbackImpl(@NonNull Context context, 306 @Nullable IInlineContentProvider inlineContentProvider, 307 @NonNull @CallbackExecutor Executor callbackExecutor, 308 @NonNull Consumer<InlineContentView> callback, 309 @Nullable InlineTooltipUi inlineTooltipUi) { 310 mContext = context; 311 mInlineContentProvider = inlineContentProvider; 312 mCallbackExecutor = callbackExecutor; 313 mCallback = callback; 314 mInlineTooltipUi = inlineTooltipUi; 315 } 316 317 @BinderThread onContent(SurfaceControlViewHost.SurfacePackage content, int width, int height)318 public void onContent(SurfaceControlViewHost.SurfacePackage content, int width, 319 int height) { 320 mMainHandler.post(() -> handleOnContent(content, width, height)); 321 } 322 323 @MainThread handleOnContent(SurfaceControlViewHost.SurfacePackage content, int width, int height)324 private void handleOnContent(SurfaceControlViewHost.SurfacePackage content, int width, 325 int height) { 326 if (!mFirstContentReceived) { 327 handleOnFirstContentReceived(content, width, height); 328 mFirstContentReceived = true; 329 } else { 330 handleOnSurfacePackage(content); 331 } 332 } 333 334 /** 335 * Called when the view content is returned for the first time. 336 */ 337 @MainThread handleOnFirstContentReceived(SurfaceControlViewHost.SurfacePackage content, int width, int height)338 private void handleOnFirstContentReceived(SurfaceControlViewHost.SurfacePackage content, 339 int width, int height) { 340 mSurfacePackage = content; 341 if (mSurfacePackage == null) { 342 mCallbackExecutor.execute(() -> mCallback.accept(/* view */null)); 343 } else { 344 mView = new InlineContentView(mContext); 345 if (mInlineTooltipUi != null) { 346 mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 347 @Override 348 public void onLayoutChange(View v, int left, int top, int right, 349 int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 350 if (mInlineTooltipUi != null) { 351 mInlineTooltipUi.update(mView); 352 } 353 } 354 }); 355 } 356 mView.setLayoutParams(new ViewGroup.LayoutParams(width, height)); 357 mView.setChildSurfacePackageUpdater(getSurfacePackageUpdater()); 358 mCallbackExecutor.execute(() -> mCallback.accept(mView)); 359 } 360 } 361 362 /** 363 * Called when any subsequent SurfacePackage is returned from the remote view owning 364 * process. 365 */ 366 @MainThread handleOnSurfacePackage(SurfaceControlViewHost.SurfacePackage surfacePackage)367 private void handleOnSurfacePackage(SurfaceControlViewHost.SurfacePackage surfacePackage) { 368 if (surfacePackage == null) { 369 return; 370 } 371 if (mSurfacePackage != null || mSurfacePackageConsumer == null) { 372 // The surface package is not consumed, release it immediately. 373 surfacePackage.release(); 374 try { 375 mInlineContentProvider.onSurfacePackageReleased(); 376 } catch (RemoteException e) { 377 Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e); 378 } 379 return; 380 } 381 mSurfacePackage = surfacePackage; 382 if (mSurfacePackage == null) { 383 return; 384 } 385 if (mSurfacePackageConsumer != null) { 386 mSurfacePackageConsumer.accept(mSurfacePackage); 387 mSurfacePackageConsumer = null; 388 } 389 } 390 391 @MainThread handleOnSurfacePackageReleased()392 private void handleOnSurfacePackageReleased() { 393 if (mSurfacePackage != null) { 394 try { 395 mInlineContentProvider.onSurfacePackageReleased(); 396 } catch (RemoteException e) { 397 Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e); 398 } 399 mSurfacePackage = null; 400 } 401 // Clear the pending surface package consumer, if any. This can happen if the IME 402 // attaches the view to window and then quickly detaches it from the window, before 403 // the surface package requested upon attaching to window was returned. 404 mSurfacePackageConsumer = null; 405 } 406 407 @MainThread handleGetSurfacePackage( Consumer<SurfaceControlViewHost.SurfacePackage> consumer)408 private void handleGetSurfacePackage( 409 Consumer<SurfaceControlViewHost.SurfacePackage> consumer) { 410 if (mSurfacePackage != null) { 411 consumer.accept(mSurfacePackage); 412 } else { 413 mSurfacePackageConsumer = consumer; 414 try { 415 mInlineContentProvider.requestSurfacePackage(); 416 } catch (RemoteException e) { 417 Slog.w(TAG, "Error calling getSurfacePackage(): " + e); 418 consumer.accept(null); 419 mSurfacePackageConsumer = null; 420 } 421 } 422 } 423 getSurfacePackageUpdater()424 private InlineContentView.SurfacePackageUpdater getSurfacePackageUpdater() { 425 return new InlineContentView.SurfacePackageUpdater() { 426 @Override 427 public void onSurfacePackageReleased() { 428 mMainHandler.post( 429 () -> InlineContentCallbackImpl.this.handleOnSurfacePackageReleased()); 430 } 431 432 @Override 433 public void getSurfacePackage( 434 Consumer<SurfaceControlViewHost.SurfacePackage> consumer) { 435 mMainHandler.post( 436 () -> InlineContentCallbackImpl.this.handleGetSurfacePackage(consumer)); 437 } 438 }; 439 } 440 441 @BinderThread onClick()442 public void onClick() { 443 mMainHandler.post(() -> { 444 if (mView != null && mView.hasOnClickListeners()) { 445 mView.callOnClick(); 446 } 447 }); 448 } 449 450 @BinderThread onLongClick()451 public void onLongClick() { 452 mMainHandler.post(() -> { 453 if (mView != null && mView.hasOnLongClickListeners()) { 454 mView.performLongClick(); 455 } 456 }); 457 } 458 } 459 460 /** 461 * This class used to provide parcelling logic for InlineContentCallbackImpl. It's intended to 462 * make this parcelling a no-op, since it can't be parceled and we don't need to parcel it. 463 */ 464 private static class InlineContentCallbackImplParceling implements 465 Parcelling<InlineContentCallbackImpl> { 466 @Override 467 public void parcel(InlineContentCallbackImpl item, Parcel dest, int parcelFlags) { 468 } 469 470 @Override 471 public InlineContentCallbackImpl unparcel(Parcel source) { 472 return null; 473 } 474 } 475 476 /** 477 * This class used to provide parcelling logic for InlineContentCallbackImpl. It's intended to 478 * make this parcelling a no-op, since it can't be parceled and we don't need to parcel it. 479 */ 480 private static class InlineTooltipUiParceling implements 481 Parcelling<InlineTooltipUi> { 482 @Override 483 public void parcel(InlineTooltipUi item, Parcel dest, int parcelFlags) { 484 } 485 486 @Override 487 public InlineTooltipUi unparcel(Parcel source) { 488 return null; 489 } 490 } 491 492 493 494 // Code below generated by codegen v1.0.22. 495 // 496 // DO NOT MODIFY! 497 // CHECKSTYLE:OFF Generated code 498 // 499 // To regenerate run: 500 // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java 501 // 502 // To exclude the generated code from IntelliJ auto-formatting enable (one-time): 503 // Settings > Editor > Code Style > Formatter Control 504 //@formatter:off 505 506 507 /** 508 * Creates a new InlineSuggestion. 509 * 510 * @param inlineContentCallback 511 * Used to keep a strong reference to the callback so it doesn't get garbage collected. 512 * @param inlineTooltipUi 513 * Used to show up the inline suggestion tooltip. 514 * @hide 515 */ 516 @DataClass.Generated.Member 517 public InlineSuggestion( 518 @NonNull InlineSuggestionInfo info, 519 @Nullable IInlineContentProvider contentProvider, 520 @Nullable InlineContentCallbackImpl inlineContentCallback, 521 @Nullable InlineTooltipUi inlineTooltipUi) { 522 this.mInfo = info; 523 com.android.internal.util.AnnotationValidations.validate( 524 NonNull.class, null, mInfo); 525 this.mContentProvider = contentProvider; 526 this.mInlineContentCallback = inlineContentCallback; 527 this.mInlineTooltipUi = inlineTooltipUi; 528 529 // onConstructed(); // You can define this method to get a callback 530 } 531 532 @DataClass.Generated.Member 533 public @NonNull InlineSuggestionInfo getInfo() { 534 return mInfo; 535 } 536 537 /** 538 * @hide 539 */ 540 @DataClass.Generated.Member 541 public @Nullable IInlineContentProvider getContentProvider() { 542 return mContentProvider; 543 } 544 545 /** 546 * Used to keep a strong reference to the callback so it doesn't get garbage collected. 547 * 548 * @hide 549 */ 550 @DataClass.Generated.Member 551 public @Nullable InlineContentCallbackImpl getInlineContentCallback() { 552 return mInlineContentCallback; 553 } 554 555 /** 556 * Used to show up the inline suggestion tooltip. 557 * 558 * @hide 559 */ 560 @DataClass.Generated.Member 561 public @Nullable InlineTooltipUi getInlineTooltipUi() { 562 return mInlineTooltipUi; 563 } 564 565 @Override 566 @DataClass.Generated.Member 567 public String toString() { 568 // You can override field toString logic by defining methods like: 569 // String fieldNameToString() { ... } 570 571 return "InlineSuggestion { " + 572 "info = " + mInfo + ", " + 573 "contentProvider = " + mContentProvider + ", " + 574 "inlineContentCallback = " + mInlineContentCallback + ", " + 575 "inlineTooltipUi = " + mInlineTooltipUi + 576 " }"; 577 } 578 579 @Override 580 @DataClass.Generated.Member 581 public boolean equals(@Nullable Object o) { 582 // You can override field equality logic by defining either of the methods like: 583 // boolean fieldNameEquals(InlineSuggestion other) { ... } 584 // boolean fieldNameEquals(FieldType otherValue) { ... } 585 586 if (this == o) return true; 587 if (o == null || getClass() != o.getClass()) return false; 588 @SuppressWarnings("unchecked") 589 InlineSuggestion that = (InlineSuggestion) o; 590 //noinspection PointlessBooleanExpression 591 return true 592 && java.util.Objects.equals(mInfo, that.mInfo) 593 && java.util.Objects.equals(mContentProvider, that.mContentProvider) 594 && java.util.Objects.equals(mInlineContentCallback, that.mInlineContentCallback) 595 && java.util.Objects.equals(mInlineTooltipUi, that.mInlineTooltipUi); 596 } 597 598 @Override 599 @DataClass.Generated.Member 600 public int hashCode() { 601 // You can override field hashCode logic by defining methods like: 602 // int fieldNameHashCode() { ... } 603 604 int _hash = 1; 605 _hash = 31 * _hash + java.util.Objects.hashCode(mInfo); 606 _hash = 31 * _hash + java.util.Objects.hashCode(mContentProvider); 607 _hash = 31 * _hash + java.util.Objects.hashCode(mInlineContentCallback); 608 _hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipUi); 609 return _hash; 610 } 611 612 @DataClass.Generated.Member 613 static Parcelling<InlineContentCallbackImpl> sParcellingForInlineContentCallback = 614 Parcelling.Cache.get( 615 InlineContentCallbackImplParceling.class); 616 static { 617 if (sParcellingForInlineContentCallback == null) { 618 sParcellingForInlineContentCallback = Parcelling.Cache.put( 619 new InlineContentCallbackImplParceling()); 620 } 621 } 622 623 @DataClass.Generated.Member 624 static Parcelling<InlineTooltipUi> sParcellingForInlineTooltipUi = 625 Parcelling.Cache.get( 626 InlineTooltipUiParceling.class); 627 static { 628 if (sParcellingForInlineTooltipUi == null) { 629 sParcellingForInlineTooltipUi = Parcelling.Cache.put( 630 new InlineTooltipUiParceling()); 631 } 632 } 633 634 @Override 635 @DataClass.Generated.Member 636 public void writeToParcel(@NonNull Parcel dest, int flags) { 637 // You can override field parcelling by defining methods like: 638 // void parcelFieldName(Parcel dest, int flags) { ... } 639 640 byte flg = 0; 641 if (mContentProvider != null) flg |= 0x2; 642 if (mInlineContentCallback != null) flg |= 0x4; 643 if (mInlineTooltipUi != null) flg |= 0x8; 644 dest.writeByte(flg); 645 dest.writeTypedObject(mInfo, flags); 646 if (mContentProvider != null) dest.writeStrongInterface(mContentProvider); 647 sParcellingForInlineContentCallback.parcel(mInlineContentCallback, dest, flags); 648 sParcellingForInlineTooltipUi.parcel(mInlineTooltipUi, dest, flags); 649 } 650 651 @Override 652 @DataClass.Generated.Member 653 public int describeContents() { return 0; } 654 655 /** @hide */ 656 @SuppressWarnings({"unchecked", "RedundantCast"}) 657 @DataClass.Generated.Member 658 /* package-private */ InlineSuggestion(@NonNull Parcel in) { 659 // You can override field unparcelling by defining methods like: 660 // static FieldType unparcelFieldName(Parcel in) { ... } 661 662 byte flg = in.readByte(); 663 InlineSuggestionInfo info = (InlineSuggestionInfo) in.readTypedObject(InlineSuggestionInfo.CREATOR); 664 IInlineContentProvider contentProvider = (flg & 0x2) == 0 ? null : IInlineContentProvider.Stub.asInterface(in.readStrongBinder()); 665 InlineContentCallbackImpl inlineContentCallback = sParcellingForInlineContentCallback.unparcel(in); 666 InlineTooltipUi inlineTooltipUi = sParcellingForInlineTooltipUi.unparcel(in); 667 668 this.mInfo = info; 669 com.android.internal.util.AnnotationValidations.validate( 670 NonNull.class, null, mInfo); 671 this.mContentProvider = contentProvider; 672 this.mInlineContentCallback = inlineContentCallback; 673 this.mInlineTooltipUi = inlineTooltipUi; 674 675 // onConstructed(); // You can define this method to get a callback 676 } 677 678 @DataClass.Generated.Member 679 public static final @NonNull Parcelable.Creator<InlineSuggestion> CREATOR 680 = new Parcelable.Creator<InlineSuggestion>() { 681 @Override 682 public InlineSuggestion[] newArray(int size) { 683 return new InlineSuggestion[size]; 684 } 685 686 @Override 687 public InlineSuggestion createFromParcel(@NonNull Parcel in) { 688 return new InlineSuggestion(in); 689 } 690 }; 691 692 @DataClass.Generated( 693 time = 1615562097666L, 694 codegenVersion = "1.0.22", 695 sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java", 696 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\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineTooltipUiParceling.class) com.android.internal.view.inline.InlineTooltipUi mInlineTooltipUi\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>,com.android.internal.view.inline.InlineTooltipUi)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)") 697 @Deprecated 698 private void __metadata() {} 699 700 701 //@formatter:on 702 // End of generated code 703 704 } 705