blob: 2d92c6aa8caf707102715f1deebaa3315129bd8a [file] [log] [blame] [view]
alanvda56d5d2021-02-12 09:00:29 -08001# Integrating proprietary components
2
3go/androidx/open_source
4
5<!--*
6# Document freshness: For more information, see go/fresh-source.
7freshness: { owner: 'alanv' reviewed: '2021-02-11' }
8*-->
9
10[TOC]
11
12One of the core principles of Jetpack is "Developed as open-source and
13compatible with AOSP Android," but what does that mean in practice? This guide
14provides specific, technical guidance on developing an open-source library and
15interacting with proprietary or closed-source libraries and services.
16
17## Why do we care?
18
19### Compatibility with AOSP ecosystem
20
21The Android Open-Source Project enables a diverse ecosystem of devices with a
22wide array of software environments in which our libraries will operate. Many of
23those devices are certified to run Play Services, but it's important for our
24libraries to work on all devices that are certified as Android -- even those
25with no Google software installed.
26
27* Features provided by primary artifacts **must** be able to function on AOSP
28 devices without the presence of proprietary components like Play Services
29
30### Testing and testability
31
32Isolating behavior makes it easier to write reliable and targeted tests, but
33introducing dependencies on proprietary components makes this difficult. In a
34well-abstracted library, developers should be able to write integration tests
35against the library's documented API surface without concerning themselves with
36the implementation details of a backing service.
37
38* Features provided by primary artifacts that may be backed by proprietary
39 components **must** be written in way that makes it feasible for a developer
40 to write and delegate to their own backing implementation
41
42## Developer choice
43
44Developers should be able to choose between proprietary components; however,
45libraries are also encouraged to provide a sensible default.
46
47* Features provided by primary artifacts that may be backed by proprietary
48 components **must** allow developers to choose a specific backing component
49 and **must not** hard-code proprietary components as the default choice
50* Libraries _may_ use a ranking or filtering heuristic based on platform APIs
51 such as permissions, presence on the system image, or other properties of
52 applications and packages
53
54## Open protocols
55
56Third-party developers should be able to provide their own backing services,
57which means service discovery mechanisms, communication protocols, and API
58surfaces used to implement a backing service must be publicly available for
59implementation.
60
61Third-party developers should also be able to validate that their implementation
62conforms to the expectations of the library. Library developers should already
63be writing tests to cover their backing service, e.g. that a service
64implementing a protocol or interface is correct, and in many cases these tests
65will be suitable for third-party developers to verify their own implementations.
66
67While we recommend that developers provide a stub backing implementation in a
68`-testing` artifact or use one in their own unit tests, we do not require one to
69be provided; only that it is possible to write one.
70
71## Examples of policy violations
72
73* A primary artifact uses `Intent` handling as a service discovery mechanism
74 and hard-codes a reference to `com.google.android` as a ranking heuristic.
75 * **What's wrong?** This conflicts with the developer choice principle.
76 Primary artifacts must remain neutral regarding specific proprietary
77 components.
78 * **How to fix?** This library should use an alternative ranking heuristic
79 that takes advantage of platform APIs such as granted permissions or
80 presence of the component on the system image (see
81 [FLAG_SYSTEM](https://developer.android.com/reference/android/content/pm/ApplicationInfo#FLAG_SYSTEM)
82 and
83 [FLAG_UPDATED_SYSTEM_APP](https://developer.android.com/reference/android/content/pm/ApplicationInfo#FLAG_UPDATED_SYSTEM_APP)).
84 The library will also need to provide an API that allows developers to
85 choose an explicit ranking or default component.
86* A primary artifact uses reflection to delegate to a specific fully-qualified
87 class name. This class is provided by an optional library that delegates to
88 Play Services.
89 * **What's wrong?** This is another situation where the library is
90 limiting developer choice. Features in primary artifacts which may
91 delegate to proprietary services must allow developers to choose a
92 different delegate. Reflection on a fully-qualified class name does
93 _not_ allow multiple delegates to exist on the classpath and is not a
94 suitable service discovery mechanism.
95 * **How to fix?** This library should use a more suitable service
96 discovery mechanism that allows multiple providers to coexist and
97 ensures the the developer is able to choose among them.
98* A primary artifact provides a service discovery mechanism that allows
99 multiple providers and exposes an API that lets the developer specify a
100 preference. Communication with the service is managed through a `Bundle`
101 where they keys, values, and behaviors are documented outside of Jetpack.
102 * **What's wrong?** This conflicts with the open protocols principle.
103 Third-party developers should be able to implement their own backing
104 services, but using a `Bundle` with a privately-documented protocol
105 means that (1) it is not possible to write adqeuate tests in Jetpack and
106 (2) developers outside of Google cannot feasibly write correct backing
107 implementations.
108 * **How to fix?** At a minimum, the developer should fully document the
109 keys, values, and behavior expected by the protocol; however, in this
110 case we would strongly recommend replacing or wrapping `Bundle` with a
111 strongly-typed and documented API surface and robust suite of tests to
112 ensure implementations on either side of the protocol are behaving
113 correctly.
114* A primary artifact provides an `interface` and an API that allows developers
115 to specify a backing service using classes that implement that interface.
116 The `interface` API surface has several `@hide` methods annotated with
117 `@RestrictTo(LIBRARY_GROUP)`.
118 * **What's wrong?** This is another open protocols issue. Third-party
119 developers should be able to implement their own backing services, but
120 using a partially-private `interface` means that only Jetpack libraries
121 can feasibly provide a backing implementation.
122 * **How to fix?** At a minimum, the developer should make the `interface`
123 fully public and documented so that it can be implemented by a
124 third-party. They should also provide robust tests for the default
125 backing implementation with the expectation that third-party developers
126 will use this to verify their own custom implementations.