blob: 77c788a4f1a0ce62952a71e3d5fc961025babe98 [file] [log] [blame] [view]
Ken Rockot686e4132017-04-26 00:03:311# Mojo Java Bindings API
Ken Rockot929282c2018-05-02 17:07:292This document is a subset of the [Mojo documentation](/mojo/README.md).
rockotf59d2d62017-04-01 02:49:083
4[TOC]
5
6## Overview
7
Ashley Newson278599d2024-05-22 15:11:028The Mojo Java Bindings API leverages the [Java System API](/mojo/public/java/system/README.md)
9to provide a more natural set of primitives for communicating over Mojo message
10pipes. Combined with generated code from the [Mojom IDL and bindings generator](/mojo/public/tools/bindings/README.md),
11users can easily connect interface clients and implementations across arbitrary
12intra- and inter-process boundaries.
rockotf59d2d62017-04-01 02:49:0813
Ashley Newson278599d2024-05-22 15:11:0214This document provides a brief guide to Java Bindings API usage with example
15code snippets. Some foundational knowledge of Mojo and mojom interface
16definitions is assumed. Familiarity with the [C++ bindings](/mojo/public/cpp/bindings/README.md)
17may be useful for comparison but isn't strictly required. For detailed API
18references you can consult the class definitions in [this directory](https://cs.chromium.org/chromium/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/).
19
20# Should I or should I not use the Java bindings?
21
22Java bindings typically only make sense on the browser side and for Android
23devices where there is some service that's unique to Android. As such, Java
24bindings are typically rarely used, but they are used sometimes. When
25implementing a cross-platform feature or service, it's probably more appropriate
26to use C++ Mojo bindings and (if necessary) plumb the platform-specific code
27implemented in Java via JNI.
28
29C++ bindings have more features than the Java bindings. In simple cases, Java
30bindings provide enough functionality to do everything by themselves. However,
31for complex usage, it may be necessary to instead use the C++ bindings and plumb
32data through JNI. See the section on notable lacking features below.
33
34However, working within Java can avoid boilerplate and complex memory management
35between C++ and Java.
36
37If your service doesn't really need to be implemented in Java (because it
38doesn't depend on or benefit from any Java-exclusive APIs), you should probably
39just write the whole thing in C++.
40
41Implementing Mojo interfaces in Java is subject to the same Chromium IPC
42[practices](/docs/security/mojo.md#Security) and [review](/docs/security/ipc-reviews.md)
43processes. However, most reviewers are used to reviewing C++ code.
44
45# Notable lacking features
46
47This is not an exhaustive list.
48
49## AssociatedInterfaces
50
51These are not supported.
52
53## ReportBadMessage
54
55There is no way for Java to report a bad message, which is the standard practice
56when the renderer sends a message that indicates it's misbehaving (and perhaps
57compromised).
58
59The best you can do if you receive a bad message is to just ignore the
60request. However, try to close any Proxy objects or InterfaceRequests that might
61not otherwise have needed closing.
62
63If the IPC call usually expects a response (via a callback), but the callback
64has not been called and the callback gets garbage collected, this will lead to
65the Mojo connection being disconnected. The involvement of the garbage collector
66makes this somewhat non-deterministic, so this behavior should not be relied
67upon.
68
69## Missing type conversions (StructTraits)
70
71There are a few non-primitive but common standard library-like mojom types. The
72C++ bindings allow the definition of custom conversions between C++ and mojom
73types via StructTraits. The auto-generated Java interfaces don't implement these
74custom conversions as they don't support StructTraits, so you don't get the
75obvious conversions between these mojom and Java types. This isn't necessarily a
76deal-breaker though, as you can still implement the conversions yourself (with
77care).
78
79An example is `String16`, representing a UTF-16 string. For `String16`, C++ can
80convert transparently to/from `std::u16string`. However, in Java, this merely
81produces something which instead resembles the underlying mojom struct - which
82just contains a `short[]` array.
83
84## Synchronous calls
85
86You cannot perform synchronous method calls _from_ Java. However, Java can still
87receive sync calls (as `[Sync]` annotations only affect the behavior on the
88caller side). In general, you shouldn't need to make synchronous calls as they
89have many [disadvantages](/mojo/public/cpp/bindings/README.md#think-carefully-before-you-decide-to-use-sync-calls).
90
91# Key differences compared to C++ bindings
92
93The Java bindings' APIs don't particularly use the terms "receiver" and
94"remote". Instead, the terms "Interface" and "Proxy" might be used. However,
95this document will often use a mixture of these terms, as "pending", "remotes",
96and "receivers" are terms used in mojom.
97
98In C++, you'll typically have a `pending_receiver<InterfaceType>` which you then
99bind to an implementation of `InterfaceType`. In Java, this is an
100`InterfaceRequest<InterfaceType>`, which can be bound to your implementation of
101`InterfaceType`.
102
103In C++, you typically have to hold on to the receiver for as long as you want it
104alive, or deliberately use a "self-owned" receiver that stays alive as long as
105the other side of the IPC connection needs it. In Java, Mojo will keep the
106underlying IPC connection and your interface implementation (receiver) alive as
107long as the other end stays alive. In practice, this behaves somewhat like
108self-owned receivers.
109
110In C++, there is generally a greater distinction between remotes and
111pending_remotes. In Java, you will typically just deal with an
112`InterfaceType.Proxy` object, which can be used as either a remote or
113pending_remote interchangeably.
114
115# Object and connection lifetimes
116
117When implementing an IPC interface, you'll also need to implement a `close()`
118method and an `onConnectionError()` method. The `close()` method will
119automatically be called whenever the IPC disconnects (either gracefully or due
120to an error). The `onConnectionError()` method will only be called (in addition
121to `close()`) when the connection ends due to an error.
122
123A Mojo connection that's bound to an implementation object will keep that object
124alive. The connection is maintained by Mojo so long as the other (remote) end is
125alive (bound or unbound). Note that calling the `close()` method on your
126interface implementation yourself won't stop calls from coming in! In java, the
127receiver generally isn't able to unilaterally end a connection cleanly.
128
129A Proxy object will keep any connection it's bound to alive until you call
130`close()` on it.
131
132No longer needed Proxy objects and InterfaceRequests which are to be discarded
133without binding should be closed. **Failing to do so can lead to resource leaks,
134produce warnings, or lead to non-deterministic crashes**. Failing to close Proxy
135objects may produce warnings in log output such as
136`java.lang.IllegalStateException: Warning: Router objects should be explicitly closed when no longer required otherwise you may leak handles.`.
137Failing to close InterfaceRequests may produce `Handle was not closed.`
138warnings.
139
140# Types
141
142## Primitive types
143
144| mojom type | non-nullable type | nullable type | Comment |
145|------------|-------------------|---------------|---------|
146| `bool` | `boolean` | `Boolean` | |
147| `int8`, `uint8` | `byte` | `Byte` | Signed and unsigned[^1] |
148| `int16`, `uint16` | `short` | `Short` | Signed and unsigned[^1] |
149| `int32`, `uint32` | `int` | `Integer` | Signed and unsigned[^1] |
150| `int64`, `uint64` | `long` | `Long` | Signed and unsigned[^1] |
151| `string` | `String` | `String` | Character encoding[^2] |
152| `array<T>` | `T[]` | `T[]` | |
153| `array<T, N>` | `T[]` | `T[]` | |
154| `map<S, T>` | `Map<S, T>` | `Map<S, T>` | |
155| `handle` | `Handle` | `Handle` | |
156| `handle<message_pipe>` | `MessagePipeHandle` | `MessagePipeHandle` | |
157| `handle<shared_buffer>` | `SharedBufferHandle` | `SharedBufferHandle` | |
158| `handle<data_pipe_producer>` | `DataPipe.ProducerHandle` | `DataPipe.ProducerHandle` | |
159| `handle<data_pipe_consumer>` | `DataPipe.ConsumerHandle` | `DataPipe.ConsumerHandle` | |
160| `pending_remote<T>` | `T` or `T.Proxy` | `T` or `T.Proxy` | Automatic conversions[^3] |
161| `pending_receiver<T>` | `InterfaceRequest<T>` | `InterfaceRequest<T>` | |
162| `pending_associated_remote<T>` | - | - | Unsupported[^4] |
163| `pending_associated_receiver<T>` | - | - | Unsupported[^4] |
164
165
166[^1]: Both signed and unsigned integers use the same Java types. Java has
167 well-defined overflow and underflow behavior. If you need to represent the
168 larger half of an unsigned number space, use the negative number space of
169 the Java integer types. For example, a uint32 with value 0xFFFFFFFF, is
170 represented by a -1 int in Java; 0xFFFFFFFE is -2; etc.
171
172[^2]: Mojom strings are UTF-8 encoded, whilst Java strings are UTF-16
173 encoded. The Java Mojo bindings will automatically translate between the two
174 encodings for you. However, you should bear in mind that certain invalid
175 Unicode strings (for example, unpaired surrogates) can result in lossy
176 conversions. (If you're dealing with binary data, you should not be using
177 strings anyway.)
178
179[^3]: Passing a `pending_remote<InterfaceType>` over IPC to Java will cause it
180 to be automatically converted to an `InterfaceType.Proxy` before it is
181 passed to any of your interface implementations. Proxy objects can also be
182 passed over IPC as pending_remotes. Java's Mojo bindings do not really make
183 a distinction between pending and non-pending remotes as C++ does and will
184 just automatically bind, unbind, and rebind them as needed when crossing IPC
185 boundaries. See the section on passing interfaces through IPC for details.
186
187[^4]: Associated interfaces are not supported in Java. Attempting to use them
188 will cause an `AssociatedInterfaceNotSupportedException` or
189 `AssociatedInterfaceRequestNotSupportedException`.
190
191## Enums
192
193```
194enum CoffeeType {
195 LATTE,
196 ESPRESSO,
197 CAPPUCCINO,
198};
199```
200
201```java
202// Non-nullable enum
203@CoffeeType.EnumType long coffeeType = CoffeeType.LATTE;
204// Nullable enum
205@CoffeeType.EnumType Long coffeeType = null;
206```
207
208Enums are just integers with an annotation.
209
210The constants for the different variants of an enum are available directly under
211the enum's generated Java class and use SCREAMING_SNAKE_CASE. (Note that this is
212unlike the tags for unions.)
213
214## Structs
215
216```
217struct BrewCoffeeRequest {
218 CoffeeType coffee_type;
219 uint64 beans;
220 double litres_of_water;
221 double litres_of_milk;
222 double kilos_of_sugar;
223 string? customer_name;
224 // Set to null to automatically allocate some cups
225 uint64? cups;
226};
227```
228
229```java
230// Create an instance. You should not make any assumptions about the default
231// state as it may be invalid.
232BrewCoffeeRequest request = new BrewCoffeeRequest();
233// Make sure to set all the fields. Each data member is public without setters
234// or getters.
235request.coffeeType = CoffeeType.LATTE;
236request.beans = 30;
237request.litresOfWater = 0.448;
238request.litresOfMilk = 0.05;
239request.kilosOfSugar = 0.002;
240request.customerName = null;
241request.cups = new Long(2);
242```
243
244As there are no getters or setters, there are no nullness checks when reading or
245writing to the data members of a struct. The members of a newly constructed
246struct object which are specified as non-nullable in the mojom may in fact be
247null-initialized and need to be filled out before the struct is sent across
248IPC. Serialization and deserialization when being sent or received across a Mojo
249channel will both perform nullness checks. If you receive a struct over IPC, it
250is guaranteed to comply with the nullability specified in the mojom file.
251
252## Unions
253
254```
255union BrewCoffeeResponse {
256 uint64 cups_of_coffee;
257 string error_message;
258};
259```
260
261```java
262// Create an instance. You should not make any assumptions about the default
263// value as it may be invalid.
264BrewCoffeeResponse response = new BrewCoffeeResponse();
265// Set it to the cups_of_coffee variant with a well-defined value.
266response.setCupsOfCoffee(2);
267// Alternatively, set it to the error_message variant.
268response.setErrorMessage("I am a teapot");
269
270// Reading a union
271switch (response.which()) {
272 case BrewCoffeeResponse.Tag.CupsOfCoffee:
273 Log.i(TAG, "We got %d cups of coffee.\n", response.getCupsOfCoffee());
274 break;
275 case BrewCoffeeResponse.Tag.ErrorMessage:
276 Log.e(TAG, "Could not brew coffee: %s\n.", response.getErrorMessage());
277 break;
278 default:
279 // Your implementation is probably out of sync with the mojom.
280 throw new IllegalArgumentException("Unknown tag");
281}
282```
283
284The content of a newly constructed union object may be null-initialized, even if
285the variant is specified as non-nullable in the mojom. Serialization and
286deserialization when being sent or received across a Mojo channel will generally
287both perform nullness checks. **(crbug.com/337849882: Invalid union data
288received over IPC may deserialize into a union with a default-constructed
289state. This may result in null content for a non-nullable variant.)**
290
291When using a getter, the autogenerated mojo code will assert that the union has
292the correct variant/tag. (This is [roughly equivalent to a DCHECK](/styleguide/java/java.md#asserts).)
293
294Java Unions internally hold the data for separate variants under separate member
295variables. These members are not cleared/nullified when other variants are set
296and therefore may continue to hold references to any nested data under them.
297
298The constants for the different tags/variants of a union are available under a
299static Tag class under the union's generated Java class and use
300PascalCase. (Note that this is unlike the variants for enums.)
301
302# Interfaces
303
304Consider the following interface used as an example in the following sections:
305
306```
307interface CoffeeMachine {
308 const double kUsCupInLitres = 0.236588;
309 const double kUsLegalCupInLitres = 0.24;
310 const double kImperialCupInLitres = 0.284131;
311
312 EnterLowPowerMode();
313 PerformCleaningCycle() => ();
314 BrewCoffee(BrewCoffeeRequest request) => (BrewCoffeeResponse response);
315};
316```
317
318## Making IPC calls
319
320```java
321// Constant names are converted to Java style
322Log.i(TAG, "There are %f US cups in 1 litre",
323 1.0 / CoffeeMachine.US_CUP_IN_LITRES);
324
325// coffeeMachine is of type CoffeeMachine.Proxy (which is itself an
326// implementation of CoffeeMachine).
327
328// Calling a method with no input, output, or even a completion callback.
329coffeeMachine.enterLowPowerMode();
330
331// Calling a method with no input or output, but that has a response callback
332// for completion.
333CoffeeMachine.PerformCleaningCycle_Response callback =
334 new CoffeeMachine.PerformCleaningCycle_Response() {
335 @Override
336 public void call() {
337 Log.i(TAG, "The cleaning cycle has finished");
338 }
339};
340coffeeMachine.performCleaningCycle(callback);
341
342// Calling a method with an input and an output.
343CoffeeMachine.BrewCoffee_Response callback =
344 new CoffeeMachine.BrewCoffee_Response() {
345 @Override
346 public void call(BrewCoffeeResponse response) {
347 // Handle the result of the brew coffee request here.
348 }
349};
350coffeeMachine.brewCoffee(brewCoffeeRequest, callback);
351```
352
353Calling these methods is asynchronous and will not block the caller.
354
355Note that calling a method with legal inputs will not itself ever fail with an
356exception if there is an IPC problem. Instead, you should set a
357`ConnectionErrorHandler` on your Proxy objects if you wish to detect errors.
358
359```java
360// coffeeMachine is of type CoffeeMachine.Proxy
361ConnectionErrorHandler connectionErrorHandler = new ConnectionErrorHandler() {
362 @Override
363 public void onConnectionError(MojoException e) {
364 // Handle the error.
365 }
366};
367coffeeMachine.getProxyHandler().setErrorHandler(connectionErrorHandler);
368```
369
370Once you are done with your Proxy object, assuming you haven't transferred it
371across IPC, make sure to close it.
372
373```java
374coffeeMachine.close();
375```
376
377Holding onto an unclosed Proxy will generally keep an IPC connection alive
378(unless the other side unilaterally closes it). If you forget to close it, you
379may leak resources (on both sides of the IPC!), get warnings, or trigger
380non-deterministic crashes.
381
382## Receiving IPC calls
383
384```java
385class CoffeeMachineImpl implements CoffeeMachine {
386 @Override
387 public void onConnectionError(MojoException e) {
388 // Handle an error here. Note that close() will also be called.
389 }
390
391 @Override
392 public void close() {
393 // Closed - either gracefully or through an error.
394 }
395
396 @Override
397 public void enterLowPowerMode() {
398 Log.i(TAG, "Zzz...");
399 }
400
401 @Override
402 public void performCleaningCycle(
403 CoffeeMachine.PerformCleaningCycle_Response callback) {
404 Log.i(TAG, "Cleaned!");
405 callback.call();
406 }
407
408 @Override
409 public void brewCoffee(
410 BrewCoffeeRequest request,
411 CoffeeMachine.BrewCoffee_Response callback) {
412 CoffeeMachine.BrewCoffeeResponse response =
413 new CoffeeMachine.BrewCoffeeResponse();
414 response.setErrorMessage("I am a teapot");
415 callback.call(response);
416 }
417}
418```
419
420When implementing a receiver for your interface, you will need to override the
421`onConnectionError(MojoException)` and `close()` methods in addition to your
422mojom-defined methods.
423
424Whilst it's technically possible for a single implementation object to be bound
425as the handler for multiple channels or receivers, you should avoid this as the
426`onConnectionError(MojoException)` and `close()` methods do not provide any
427explicit information about which channel their calls relate to. It's also
428conceptually confusing if you continue to use a `Closeable` that may have been
429closed.
430
431Note that a Mojo connection that's bound to an implementation object will keep
432that implementation object alive. However, your implementation object has no
433inherent influence over the lifetime of the connection (after all, you're just
434implementing an interface).
435
436# Registering, mapping, binding, and passing interfaces
437
438## Working with interface brokers
439
440Interface brokers are how the renderer process usually obtains access to an IPC
441interface. In Java, this will typically bind the receiver implementations for
442you.
443
444See a few examples from [code search](https://source.chromium.org/search?q=language:java%20class:InterfaceRegistrar&sq=).
445There are a few examples for general registrars for Android WebView and Chrome
446on Android. You will likely be able to re-use one of these for your purposes.
447
448Adding your implementation to the binder mapping happens in the normal C++
449`*_bindings.cc` or `*_binders.cc` files, which are subject to IPC security
450reviews. The mapping code will route over to the Java implementation. An
451`InterfaceRegistrar`, `InterfaceRegistry`, and a factory for your implementation
452class is typically used to perform the binding of an implementation to an
453interface that's obtained via the browser interface broker.
454
455Much as how different layers or components use different `*_bindings.cc` and
456`*_binders.cc` files to expose your IPC implementation via interface brokers,
457there are also different interface registrars. Sometimes, their
458approaches/implementations can be a little inconsistent. Choosing which
459interface registrar to use, or creating an entirely new one, is dependent on the
460use case and is outside of the scope of this document. We will only briefly look
461at adding a hypothetical blink-defined "CoffeeMachine" interface to Android
462WebView as an example.
463
464`//android_webview/browser/aw_content_browser_client_receiver_bindings.cc`:
465
466```c++
467template <typename Interface>
468void ForwardToJavaFrame(content::RenderFrameHost* render_frame_host,
469 mojo::PendingReceiver<Interface> receiver) {
470 render_frame_host->GetJavaInterfaces()->GetInterface(std::move(receiver));
471}
472
473void BindCoffeeMachineReceiver(
474 content::RenderFrameHost* render_frame_host,
475 mojo::PendingReceiver<blink::mojom::CoffeeMachine> receiver) {
476 // Optional: if you wanted to perform any pre-binding checks, such as to
477 // make sure that the origin is secure, etc, now is the time to do it:
478 const url::Origin& origin = render_frame_host->GetLastCommittedOrigin();
479 if (!network::IsOriginPotentiallyTrustworthy(origin)) {
480 mojo::ReportBadMessage(
481 "Attempted to access CoffeeMachine from non-trustworthy origin.");
482 return;
483 };
484
485 ForwardToJavaFrame<blink::mojom::CoffeeMachine>(
486 render_frame_host, std::move(receiver));
487}
488
489void AwContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
490 content::RenderFrameHost* render_frame_host,
491 mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
492 map->Add<blink::mojom::CoffeeMachine>(
493 base::BindRepeating(&BindCoffeeMachineReceiver));
494 // ... Mappings for other interfaces
495}
496```
497
498`//android_webview/java/src/org/chromium/android_webview/AwInterfaceRegistrar.java`:
499
500```java
501class AwInterfaceRegistrar {
502 @CalledByNative
503 private static void registerMojoInterfaces() {
504 InterfaceRegistrar.Registry.addRenderFrameHostRegistrar(
505 new AndroidWebviewRenderFrameHostInterfaceRegistrar());
506 }
507
508 private static class AndroidWebviewRenderFrameHostInterfaceRegistrar
509 implements InterfaceRegistrar<RenderFrameHost> {
510 @Override
511 public void registerInterfaces(
512 InterfaceRegistry registry,
513 RenderFrameHost renderFrameHost) {
514 // A made up example:
515 registry.addInterface(
516 CoffeeMachineImpl.MANAGER,
517 new CoffeeMachineImplFactory(renderFrameHost));
518 // ... Calls for other interfaces.
519 }
520 }
521}
522```
523
524`CoffeeMachineImplFactory.java`:
525
526```java
527public class CoffeeMachineImplFactory implements InterfaceFactory {
528 private final RenderFrameHost mRenderFrameHost;
529
530 public CoffeeMachineFactory(RenderFrameHost renderFrameHost) {
531 mRenderFrameHost = renderFrameHost;
532 }
533
534 @Override
535 public CoffeeMachineImpl createImpl() {
536 return new CoffeeMachineImpl(mRenderFrameHost);
537 }
538}
539```
540
541However, if you're passing pending_receivers around as part of the IPC calls of
542your interfaces, you will need to do the binding yourself, as described in the
543next sections.
544
545
546
547
548
549## Passing interfaces through IPC calls (pending_receivers and pending_remotes)
550
551Consider the following interfaces used as an example in the following sections:
552
553```
554interface CoffeeMachine {
555 BrewCoffee(BrewCoffeeRequest request) => (BrewCoffeeResponse response);
556 // ...
557};
558
559interface Employee {
560 ProvideCoffeeAccess(pending_remote<CoffeeMachine> coffee_machine);
561};
562
563interface Kitchen {
564 RequestCoffeeAccess(pending_receiver<CoffeeMachine> coffee_machine);
565};
566```
567
568### Receiving a pending_receiver and binding to it
569
570There is a bit of a terminology mismatch in Java compared to C++/mojom where
571Java uses some older phrasing. Notably, pending_receivers are called
572"InterfaceRequests" in Java (this actually used to be the old term used in other
573bindings like C++). Once received on the Java side, these can then be bound to
574an implementation.
575
576```java
577class KitchenImpl implements Kitchen {
578 // ...
579 @Override
580 public void requestCoffeeAccess(
581 InterfaceRequest<CoffeeMachine> interfaceRequest) {
582 CoffeeMachine coffeeMachine = new CoffeeMachineImpl();
583 CoffeeMachine.MANAGER.bind(coffeeMachine, interfaceRequest);
584 }
585}
586```
587
588If you do not intend to bind an implementation to an InterfaceRequest and
589instead wish to just discard it, you should `close()` it.
590
591### Receiving a pending_remote and using it
592
593Pending remotes are automatically bound and converted to Proxy objects when
594received.
595
596```java
597class EmployeeImpl implements Employee {
598 // ...
599 @Override
600 public void provideCoffeeAccess(CoffeeMachine coffeeMachine) {
601 // We can immediately use the remote/proxy
602 coffeeMachine.brewCoffee(mMyUsualPlease, mDrinkCoffeeCallback);
603 coffeeMachine.close();
604
605 // Or, we could pass the proxy onto somewhere else, and it will be
606 // unbound from the proxy and converted from a remote back into a
607 // pending remote.
608 mColleague.provideCoffeeAccess(coffeeMachine);
609 // Do not close() if passed elsewhere.
610 }
611}
612```
613
614If you are finished with the remote/proxy (and have not passed it on elsewhere),
615you should `close()` it.
616
617### Creating and sending pending_receivers and pending_remotes
618
619You can create a connected pair of an `InterfaceType.Proxy` and an
620`InterfaceRequest<InterfaceType>`. You can then either use these yourself or
621send them over IPC.
622
623```java
624// import org.chromium.mojo.system.Pair;
625// import org.chromium.mojo.system.impl.CoreImpl;
626
627Pair<CoffeeMachine.Proxy, InterfaceRequest<CoffeeMachine>> pair =
628 CoffeeMachine.MANAGER.getInterfaceRequest(CoreImpl.getInstance());
629
630// Both the proxy and the interface request can used by us or be sent over IPC.
631// Note that calls can be queued via the proxy/remote even before the
632// pending_receiver/interface request is bound to an implementation.
633employee.provideCoffeeAccess(pair.first);
634kitchen.requestCoffeeAccess(pair.second);
635```
636
637There is a shortcut if you want to provide the other side of the IPC with a
638remote to an implementation you own. Instead of creating a pair of a Proxy and
639an InterfaceRequest, you can directly supply your implementation object instead
640of a proxy and Mojo will create, bind, and send a pending remote for you:
641
642```java
643CoffeeMachine coffeeMachine = new CoffeeMachineImpl()
644employee.provideCoffeeAccess(coffeeMachine);
645```
646
647Note that whether you send a pending_remote one way or send a pending_receiver
648the other way can have an effect on ownership, lifetimes, and performance. It
649may be better to supply a pending_receiver as an argument to a method call than
650to wait for a pending_remote from the response callback - especially if you want
651to queue up messages before all binding has taken place.
652
653# Threading
654
655When receiving IPC calls, Mojo will invoke your interface implementation's
656methods on the thread/sequence on which the implementation was bound. This also
657extends to the `close` and `onConnectionError` methods. (This is similar to how
658things work in C++.)
659
660You should generally only use the Mojo APIs from within a valid sequence, though
661purely manipulating mojom-generated Java data types (structs, enums, unions) is
662OK. Various Mojo method calls will crash if invoked from outside of a valid
663sequence.
664
665Note that ordinary Proxy objects are not thread safe and should generally only
666be used from the thread on which they are created. However, you can create a
667thread safe wrapper around your proxy object using
668`InterfaceType.MANAGER.buildThreadSafeProxy(originalProxy)`, which will forward
669calls to the thread on which the thread-safe proxy wrapper was created. You must
670therefore build the thread-safe proxy from the thread which owns the original
671proxy.