This page contains answers to frequently asked questions about GrapheneOS. It's not
an overview of the project or a list of interesting topics about GrapheneOS. Many of
the answers would be nearly the same or identical for the latest release of the
Android Open Source Project. The goal is to provide high quality answers to some of
the most common questions about the project, so the developers and other community
members can link to these and save lots of time while also providing higher quality
answers.
GrapheneOS has official production support for the following devices:
- Pixel Fold (felix)
- Pixel Tablet (tangorpro)
- Pixel 7a (lynx)
- Pixel 7 Pro (cheetah)
- Pixel 7 (panther)
- Pixel 6a (bluejay)
- Pixel 6 Pro (raven)
- Pixel 6 (oriole)
- Pixel 5a (barbet)
- Pixel 5 (redfin)
- Pixel 4a (5G) (bramble)
- Pixel 4a (sunfish)
The following devices are end-of-life, no longer receive full security
updates and are supported via extended support releases of GrapheneOS:
- Pixel 4 XL (coral)
- Pixel 4 (flame)
We provide extended support releases as a stopgap for users to transition
to the far more secure current generation devices.
The release tags for these devices have official builds and updates
available. These devices meet the stringent privacy and security standards and
have substantial upstream and downstream hardening specific to the
devices.
Many other devices are supported by GrapheneOS at a source level, and it can be
built for them without modifications to the existing GrapheneOS source tree. Device
support repositories for the Android Open Source Project can simply be dropped into
the source tree, with at most minor modifications within them to support GrapheneOS.
In most cases, substantial work beyond that will be needed to bring the support up to
the same standards. For most devices, the hardware and firmware will prevent providing
a reasonably secure device, regardless of the work put into device support.
GrapheneOS also supports generic targets, but these aren't suitable for production
usage and are only intended for development and testing use. For mobile devices, the
generic targets simply run on top of the underlying device support code (firmware,
kernel, device trees, vendor code) rather than shipping it and keeping it updated. It
would be possible to ship generic system images with separate updates for the device
support code. However, it would be drastically more complicated to maintain and
support due to combinations of different versions and it would cause complications for
the hardening done by GrapheneOS. The motivation doesn't exist for GrapheneOS, since
full updates with deltas to minimize bandwidth can be shipped for every device and
GrapheneOS is the only party involved in providing the updates. For the same reason,
it has little use for the ability to provide out-of-band updates to system image
components including all the apps and many other components.
Some of the GrapheneOS sub-projects support other operating systems on a broader
range of devices. Device support for Auditor and AttestationServer is documented in
the overview of those projects. The
hardened_malloc project
supports nearly any Linux-based environment due to official support for musl, glibc
and Bionic along with easily added support for other environments. It can easily run
on non-Linux-based operating systems too, and supporting some like HardenedBSD is
planned but depends on contributors from those communities.
We strongly recommend only purchasing one of the following
devices for GrapheneOS due to better security and a minimum 5 year guarantee
from launch for full security updates and other improvements:
- Pixel Fold
- Pixel Tablet
- Pixel 7a
- Pixel 7 Pro
- Pixel 7
- Pixel 6a
- Pixel 6 Pro
- Pixel 6
Newer devices have more of their 5 year minimum guarantee remaining but the
actual support time may be longer than the minimum guarantee.
The Pixel 7 and Pixel 7 Pro are all around improvements over the Pixel 6
and Pixel 6 Pro with a significantly better GPU and cellular radio along with
an incremental CPU upgrade. The 7th generation Pixels are far more similar to
the previous generation than any prior Pixels.
Pixel 7a is nearly the same as the Pixel 7 other than having slow wireless
charging and weaker dust/water protection. Pixel 7a offers the best value when
buying a new device.
The Pixel Tablet is a tablet variant of the 7th generation devices and the
Pixel Fold is a hybrid phone/tablet. These share the same SoC and are nearly
the same as the other 7th generation devices under the hood.
Pixel 6, Pixel 6 Pro and Pixel 6a can still be worth buying if you can get
a good deal due to the long support time. They still have 3.5 to 4 years of
their minimum support guarantee remaining.
Devices are carefully chosen based on their merits rather than the project aiming
to have broad device support. Broad device support is counter to the aims of the
project, and the project will eventually be engaging in hardware and firmware level
improvements rather than only offering suggestions and bug reports upstream for those
areas. Much of the work on the project involves changes that are specific to different
devices, and officially supported devices are the ones targeted by most of this
ongoing work.
Devices need to be meeting the standards of the project in order to be considered as
potential targets. In addition to support for installing other operating systems,
standard hardware-based security features like the hardware-backed keystores, verified
boot, attestation and various hardware-based exploit mitigations need to be available.
Devices also need to have decent integration of IOMMUs for isolating components such
as the GPU, radios (NFC, Wi-Fi, Bluetooth, Cellular), media decode / encode, image
processor, etc., because if the hardware / firmware support is missing or broken,
there's not much that the OS can do to provide an alternative. Devices with support for
alternative operating systems as an afterthought will not be considered. Devices need
to have proper ongoing support for their firmware and software specific to the hardware
like drivers in order to provide proper full security updates too. Devices that are
end-of-life and no longer receiving these updates will not be supported.
In order to support a device, the appropriate resources also need to be available
and dedicated towards it. Releases for each supported device need to be robust and
stable, with all standard functionality working properly and testing for each of the
releases.
Hardware, firmware and software specific to devices like drivers play a huge role
in the overall security of a device. The goal of the project is not to slightly
improve some aspects of insecure devices and supporting a broad set of devices would
be directly counter to the values of the project. A lot of the low-level work also
ends up being fairly tied to the hardware.
Broader device support can only happen after the community (companies,
organizations and individuals) steps up to make substantial, ongoing contributions to
making the existing device support sustainable. Once the existing device support is
more sustainable, early research and development work for other devices can begin.
Once a device is deemed to be a worthwhile target, the project needs maintainers to
develop and maintain support for it including addressing device-specific issues that
are uncovered, which will include issues uncovered in the device support code by
GrapheneOS hardening features.
It's not really a matter of time but rather a need for community support for the
project increasing. As an open source project, the way to get something to happen in
GrapheneOS is to contribute to it, and this is particularly true for device support
since it's very self-contained and can be delegated to separate teams for each
device. If you want to see more devices supported sooner, you should get to work on
identifying good devices with full support for alternative operating systems with
verified boot, etc. and then start working on integrating and testing support.
It should also be clear that the expectation is for people to buy a device to run
GrapheneOS, rather than GrapheneOS supporting their existing devices. This will only
become more true if GrapheneOS is successful enough to accomplish the goal of having
devices produced based on an SoC reference design with minor improvements for privacy
and security. Broad device support is the opposite of what the project wants to
achieve in the long term.
GrapheneOS aims to provide reasonably private and secure devices. It cannot do that
once device support code like firmware, kernel and vendor code is no longer actively
maintained. Even if the community was prepared to take over maintenance of the open
source code and to replace the rest, firmware would present a major issue, and the
community has never been active or interested enough in device support to consider
attempting this. Unlike many other platforms, GrapheneOS has a much higher minimum
standard than simply having devices fully functional, as they also need to provide the
expected level of security. It would start to become realistic to provide
substantially longer device support once GrapheneOS controls the hardware and firmware
via custom hardware manufactured for it. Until then, the lifetime of devices will
remain based on manufacturer support. It's also important to keep in mind that phone
vendors claiming to provide longer support often aren't actually doing it and some
never even ship firmware updates when the hardware is still supported by the
vendors...
GrapheneOS also has high standards for the privacy and security properties of the
hardware and firmware, and these standards are regularly advancing. The rapid pace of
improvement has been slowing down, but each hardware generation still brings major
improvements. Over time, the older hardware starts to become a substantial liability
and holds back the project. It becomes complex to simply make statements about the
security of the project when exceptions for old devices need to be listed out. The
project ends up wanting to drop devices for this reason but has always kept them going
until the end-of-life date to provide more time for people to migrate.
The following devices are no longer supported:
- Pixel 3a XL (bonito)
- Pixel 3a (sargo)
- Pixel 3 XL (crosshatch)
- Pixel 3 (blueline)
- Pixel 2 XL (taimen)
- Pixel 2 (walleye)
- Pixel XL (marlin)
- Pixel (sailfish)
- Nexus 6P (angler)
- Nexus 5X (bullhead)
- Nexus 9 (flounder)
- Nexus 5 (hammerhead)
- Samsung Galaxy S4 (jflte)
GrapheneOS also used to provide official support for the following
development boards (without publishing official builds) but dropped support
due to lack of community interest and lack of hardware availability:
- HiKey 960 (hikey960)
- HiKey (hikey)
GrapheneOS can only fully provide security updates to a device provided
that the OEM is releasing them. When an OEM is no longer providing security
updates, GrapheneOS aims to provide harm reduction releases for devices which
only have a minimum of 3 years support. Extended support updates at minimum
will be done until the next Android version. It is likely that we will make a
decision around harm reduction releases for other devices with longer
lifetimes in Q4 2024. Harm reduction releases do not have complete security
patches because it's not possible to provide full security updates for the
device without OEM support and they are intended to buy users some limited
time to migrate to a supported device.
| Device |
OEM minimum support end |
OEM minimum support length |
| Google Pixel Fold |
June 2028 |
5 years |
| Google Pixel Tablet |
June 2028 |
5 years |
| Google Pixel 7a |
May 2028 |
5 years |
| Google Pixel 7 Pro |
October 2027 |
5 years |
| Google Pixel 7 |
October 2027 |
5 years |
| Google Pixel 6a |
July 2027 |
5 years |
| Google Pixel 6 Pro |
October 2026 |
5 years |
| Google Pixel 6 |
October 2026 |
5 years |
| Google Pixel 5a |
August 2024 |
3 years |
| Google Pixel 5 |
October 2023 |
3 years |
| Google Pixel 4a 5G |
November 2023 |
3 years |
| Google Pixel 4a |
August 2023 |
3 years |
| Google Pixel 4 |
October 2022 |
3 years |
| Google Pixel 4 XL |
October 2022 |
3 years |
GrapheneOS uses an enhanced version of the modern filesystem-based disk
encryption implementation in the Android Open Source Project. The officially
supported devices have substantial hardware-based support for enhancing the
security of the encryption implementation. GrapheneOS has full support for the
hardware-based encryption features just as it does with other hardware-based
security features.
Firmware and OS partitions are identical copies of the images published in
the official releases. The authenticity and integrity of these partitions is
verified from a root of trust on every boot. No data is read from any of these
images without being cryptographically verified. Encryption is out of scope
due to the images being publicly available. Verified boot offers much stronger
security properties than disk encryption. Further details will be provided in
another section on verified boot in the future.
The data partition stores all of the persistent state for the operating
system. Full disk encryption is implemented via filesystem-based encryption
with metadata encryption. All data, file names and other metadata is always
stored encrypted. This is often referred to as file-based encryption but it
makes more sense to call it filesystem-based encryption. It's implemented by
the Linux kernel as part of the ext4 / f2fs implementation rather than running
a block-based encryption layer. The advantage of filesystem-based encryption
is the ability to use fine-grained keys rather than a single global key that's
always in memory once the device is booted.
Disk encryption keys are randomly generated with a high quality CSPRNG and
stored encrypted with a key encryption key. Key encryption keys are derived at
runtime and are never stored anywhere.
Sensitive data is stored in user profiles. User profiles each have their
own unique, randomly generated disk encryption key and their own unique key
encryption key is used to encrypt it. The owner profile is special and is used
to store sensitive system-wide operating system data. This is why the owner
profile needs to be logged in after a reboot before other user profiles can be
used. The owner profile does not have access to the data in other profiles.
Filesystem-based encryption is designed so that files can be deleted without
having the keys for their data and file names, which enables the owner profile
to delete other profiles without them being active.
GrapheneOS enables support for ending secondary user profile sessions after
logging into them. It adds an end session button to the lockscreen and in the
global action menu accessed by holding the power button. This fully purges the
encryption keys and puts the profiles back at rest. This can't be done for the
owner profile without rebooting due to it encrypting the sensitive system-wide
operating system data.
Using a secondary profile for regular usage allows you to make use of the
device without decrypting the data in your regular usage profile. It also
allows putting it at rest without rebooting the device. Even if you use the
same passphrase for multiple profiles, each of those profiles still ends up
with a unique key encryption key and a compromise of the OS while one of them
is active won't leak the passphrase. The advantage to using separate
passphrases is in case an attacker records you entering it.
File data is encrypted with AES-256-XTS and file names with AES-256-CTS. A
unique key is derived using HKDF-SHA512 for each regular file, directory and
symbolic link from the per-profile encryption keys, or the global encryption
key for non-sensitive data stored outside of profiles. The directory key is
used to encrypt the file names. GrapheneOS increases the file name padding
from 16 bytes to 32 bytes. AES-256-XTS with the global encryption key is also
used to encrypt filesystem metadata as a whole beyond the finer-grained file
name encryption.
The OS derives a password token from the profile's lock method credential
using scrypt. This is used as the main input for key derivation.
The OS stores a high entropy random value as the Weaver token on the secure
element (Titan M on Pixels) and uses it as another input for key derivation.
The Weaver token is stored alongside a Weaver key derived by the OS from the
password token. In order to retrieve the Weaver token, the secure element
requires the correct Weaver key. A secure internal timer is used to implement
hardware-based delays for each attempt at key derivation. It quickly ramps up
to 1 day delays before the next attempt. Weaver also provides reliable wiping
of data since the secure element can reliably wipe a Weaver slot. Deleting a
profile will wipe the corresponding Weaver slot and a factory reset of the
device wipes all of the Weaver slots. The secure element also provides insider
attack resistance preventing firmware updates before authenticating with the
owner profile.
Standard delays for encryption key derivation enforced by the secure
element:
- 0 to 4 failed attempts: no delay
- 5 failed attempts: 30 second delay
- 6 to 9 failed attempts: no delay
- 10 to 29 failed attempts: 30 second delay
- 30 to 139 failed attempts: 30 × 2⌊(n - 30) ÷ 10⌋
where n is the number of failed attempts. This means the delay
doubles after every 10 attempts. There's a 30 second delay after 30 failed
attempts, 60s after 40, 120s after 50, 240s after 60, 480s after 70, 960s
after 80, 1920s after 90, 3840s after 100, 7680s after 110, 15360s after
120 and 30720s after 130
- 140 or more failed attempts: 86400 second delay (1 day)
Invalid input outside the minimum or maximum length limits of the UI won't
trigger an attempt at authentication or key derivation.
GrapheneOS only officially supports devices with Weaver. The fallback
implementation for devices without it is out-of-scope for this FAQ.
The password token, Weaver token and other values like the OS verified boot
key are used by the TEE as inputs to a hardware-bound key derivation algorithm
provided by the SoC. The general concept is having the SoC perform hardware
accelerated key derivation using an algorithm like AES or HMAC keyed with a
hard-wired hardware key inaccessible to software or firmware. This is meant to
prevent offloading a brute force attack onto more powerful hardware without an
expensive process of extracting the hardware key from the SoC.
Many apps use the hardware keystore, their own encryption implementation or
a combination of those to provide an additional layer of encryption. As an
example, an app can use the hardware keystore to encrypt their data with a key
only available when the device is unlocked to keep their data at rest when the
profile is locked but not logged out. This is beyond the scope of this FAQ
section.
As of Android 10, only the configured default input method editor (your keyboard of
choice) and the currently focused app can access the clipboard. Apps without focus
cannot access the clipboard. This is a stricter restriction than preventing apps in
the background from accessing it, since an app in the foreground or a foreground
service cannot access it, only the foreground app that's currently focused. Clipboard
managers need to be implemented by the keyboard chosen as the default by the user.
GrapheneOS previously restricted background clipboard access as a much earlier and
slightly less strict implementation of this feature. It provided a toggle for users to
whitelist clipboard managers, which is no longer needed now that keyboards are
expected to provide it.
As of Android 12, the user is notified when an app reads clipboard content
which was set by a different app. This notice is enabled by default and can be
toggled under Settings ➔ Privacy ➔ Show clipboard access.
As of Android 10, apps cannot obtain permission to access non-resettable hardware
identifiers such as the serial number, MAC addresses, IMEIs/MEIDs, SIM card serial
numbers and subscriber IDs. Only privileged apps included in the base system with
READ_PRIVILEGED_PHONE_STATE
whitelisted can access these hardware
identifiers. Apps targeting Android 10 will receive a SecurityException
and older apps will receive an empty value for compatibility.
Since these restrictions became standard, GrapheneOS only makes a small change to
remove a legacy form of access to the serial number by legacy apps, which was still
around for compatibility. It used to need more extensive changes such as disallowing
access to the serial number but those restrictions are now standard.
Apps can determine the model of the device (such as it being a Pixel 6) either
directly or indirectly through the properties of the hardware and software. There
isn't a way to avoid this short of the OS supporting running apps in a virtual machine
with limited functionality and hardware acceleration. Hiding the CPU/SoC model would
require not even using basic hardware virtualization support and these things could
probably still be detected via performance measurements.
In addition to not having a way to identify the hardware, apps cannot directly
identify the installation of the OS on the hardware. Apps only have a small portion of
the OS configuration exposed to them and there is not much for device owners to change
which could identify their installation. Apps can detect that they're being run on
GrapheneOS via the privacy and security features placing further restrictions on them
and hardening them against further exploitation. Apps can identify their own app
installation via their app data and can directly (until that's removed) or indirectly
identify a profile. Profiles should be used when separate identities are desired.
Profiles can be used as temporary ephemeral identities by creating them for a specific
need and then deleting them. The rest of this answer only provides more technical
details, so you can stop reading here if you only want an overview and actionable
advice (i.e. use profiles as identities not inherently tied to each other).
Examples of the global OS configuration available to apps are time zone,
network country code and other similar global settings. Per-profile examples
are dark mode and language. Similar to extension and browser configuration /
state being fingerprinted by web sites, an app could use a combination of
these things in an attempt to identify the installation. All of these things
vary at runtime and can be changed, but some are fairly unlikely to change in
practice after the initial setup of the device such as the ones listed above.
GrapheneOS will likely add further restrictions in this area and a couple
toggles for certain cases like time zones to use a standard value instead.
Apps can generate their own 128-bit or larger random value and use that as an
identifier for the app installation. Apps can create data in their app-specific
external storage directory by default without needing permission, and in the legacy
storage model before API 29 that data persists after the app is uninstalled, so it can
be used to store an ID that persists through the app being uninstalled and
reinstalled. However, external storage is under control of the user and the user can
delete this data at any time, including after uninstalling the app. In the modern
storage model, this data is automatically removed when the app is uninstalled.
GrapheneOS includes Seedvault as an OS backup service which must be explicitly
enabled, and it has the option to automatically restore app data when an app is
reinstalled, so it wouldn't lose track of it being the same profile.
The ANDROID_ID string is a 64-bit random number, unique to each
combination of profile and app signing key. The 64-bit limitation means it isn't
particularly useful due to the possibility of collisions. It's tied to the lifetime of
profiles and does not persist through profile deletion or a factory reset. This is
comparable to an app targeting the legacy storage model storing a 64-bit random value
in the app-specific external storage directory. In the future, GrapheneOS will likely
change this to be tied to the lifetime of app installations rather than profiles. An
app could still track the identity of the profile through data you give it access to or
via data another app chooses to share with them.
The advertising ID is a Google Play services feature not included in the baseline
Android API, so it isn't an API included in GrapheneOS. The advertising ID is unique
to each profile. It isn't unique to each app signing key like ANDROID_ID,
but that makes little difference since apps within the same profile can communicate
with each other with mutual consent. It's comparable to ANDROID_ID but
provides an 128-bit value so it provides a strong cryptographic guarantee against
collisions, although a device messing with apps could set it to the same value used in
another profile. The advertising ID is exposed via the Settings app and can be reset
to a new random value, unlike ANDROID_ID which remains the same for the
lifetime of the profile, but apps can tie it to the previous ID since they can detect
that it changed via their own ID in their app data. The advertising ID can
also now be disabled (zeroed).
Apps do not have access to user data by default and cannot ever access the data of
other apps without those apps going out of the way to share it with them. If apps are
granted read access to user data like media or contacts, they could use it to identify
the profile. If apps are granted write access to user data, they could tag it to keep
track of the profile. Apps previously had little reason to do things like this because
they were able to persist data through an uninstall and reinstallation by default. The
modern storage model means they need to request access to user data to do this. The
existence of ANDROID_ID means they don't yet need to bother with that but
that will change on GrapheneOS and will likely change for baseline Android too.
However, profiles are the only way to provide a strong assurance of separate
identities since the application model of the OS is designed to support communication
between apps within the same profile, but never between them.
GrapheneOS always considers networks to be hostile and avoids placing trust in
them. It leaves out various carrier apps included in the stock OS granting carriers
varying levels of administrative access beyond standard carrier configuration.
GrapheneOS also avoids trust in the cellular network in other ways including providing
a secure network time update implementation rather than trusting the cellular network
for this. Time is sensitive and can be used to bypass security checks depending on
certificate / key expiry.
Cellular networks use inherently insecure protocols and have many trusted parties.
Even if interception of the connection or some other man-in-the-middle attack along
the network is not currently occurring, the network is still untrustworthy and
information should not be sent unencrypted.
Authenticated transport encryption such as HTTPS for web sites avoids trusting the
cellular network. End-to-end encrypted protocols such as the Signal messaging protocol
also avoid trusting the servers. GrapheneOS uses authenticated encryption with modern
protocols, forward secrecy and strong cipher configurations for our services. We only
recommend apps taking a decent approach in this area.
Legacy calls and texts should be avoided as they're not secure and trust the
carrier / network along with having weak security against other parties. Trying to
detect some forms of interception rather than dealing with the root of the problem
(unencrypted communications / data transfer) would be foolish and doomed to
failure.
GrapheneOS does not add gimmicks without a proper threat model and
rationale. We won't include flawed heuristics to guess when the cellular
network should be trusted. These kinds of features provide a false sense of
security and encourage unwarranted trust in cellular protocols and carrier
networks as the default. These also trigger false positives causing
unnecessary concern and panic. The correct approach is avoiding trusting the
network as explained above.
Connecting to your carrier's network inherently depends on you identifying yourself to
it and anyone able to obtain administrative access. Activating airplane mode will
fully disable the cellular radio transmit and receive capabilities, which will prevent
your phone from being reached from the cellular network and stop your carrier (and
anyone impersonating them to you) from tracking the device via the cellular radio. The
baseband implements other functionality such as Wi-Fi and GPS functionality, but each
of these components is separately sandboxed on the baseband and independent of each
other. Enabling airplane mode disables the cellular radio, but Wi-Fi can be re-enabled
and used without activating the cellular radio again. This allows using the device as
a Wi-Fi only device.
The LTE-only mode added by GrapheneOS is solely
intended for attack surface reduction. It should not be mistaken as a way to make
the cellular network into something that can be trusted.
Receiving a silent SMS is not a good indicator of being targeted by your cell
carrier, police or government because anyone on the cell network can send
them including yourself. Cellular triangulation will happen regardless of whether
or not SMS texts are being sent or received by the phone. Even if an SMS did serve a
useful purpose for tracking, a silent SMS would be little different than receiving
unsolicited spam. In fact, sending spam would be stealthier since it wouldn't trigger
alerts for silent SMS but rather would be ignored with the rest of the spam. Regardless,
sending texts or other data is not required or particularly useful to track devices
connected to a network for an adversary with the appropriate access.
Airplane mode is the only way to avoid the cellular network tracking your
device and works correctly on the devices we support.
See the usage guide section on Wi-Fi privacy.
By default, GrapheneOS only makes remote connections to GrapheneOS services
and the network provided DNS resolvers. There aren't any analytics/telemetry
in GrapheneOS. The only information revealed to the GrapheneOS servers are the
generic device model (such as Pixel 7 Pro) and OS version which are necessary
for obtaining updates. The default connections provide the OS and apps with
updates, set the system clock, check each network connection for internet
connectivity, download a global database (does not vary based on location)
with predicted satellite locations when using Location and obtain attestation
chain signing keys for the hardware keystore needed for the hardware-based
attestation feature.
Make sure to read the other connections
section below this one too which covers non-default connections triggered by
having a certain carrier, having apps installed, etc.
The expected default connections by GrapheneOS (including all base system apps) are
the following:
-
The GrapheneOS System Updater app fetches update metadata from
https://releases.grapheneos.org/DEVICE-CHANNEL approximately once every four hours
when connected to a permitted network for updates.
Once an update is available, it tries to download
https://releases.grapheneos.org/DEVICE-incremental-OLD_VERSION-NEW_VERSION.zip
for a delta update, and then falls back to
https://releases.grapheneos.org/DEVICE-ota_update-NEW_VERSION.zip.
No query / data is sent to the server, so the only information given to it
are the variables in these 3 URLs (device, channel, current version) which is
necessary to obtain the update.
Users are in control of which types of networks the Updater app will use
and can disable the Updater app in extreme cases. It's strongly recommended to
leave it enabled to quickly receive security updates including updates outside
the regular monthly schedule.
The update client avoids trusting the data obtained from the update server
via signature verification with downgrade protection. Verified boot provides
another layer of signature verification with downgrade protection. GrapheneOS
servers do not have access to GrapheneOS signing keys.
See the usage guide's section on updates for
more information.
-
The GrapheneOS app repository client (Apps) fetches generic signed
update metadata and signed package updates (APKs) from
https://apps.grapheneos.org/ (a separate name for the same servers as
https://releases.grapheneos.org). It provides out-of-band updates to
certain apps bundled with the OS and other apps available in our
repository.
-
Vanadium, our browser and WebView implementation, uses
update.vanadium.app
to check for updates to components
providing revoked certificates and other data. It downloads the
components from dl.vanadium.app
.
-
An HTTPS connection is made to
https://time.grapheneos.org/generate_204 to update the time with a
millisecond precision X-Time header. As part of future support for
using other services, it falls back to the standard Date header with
second precision.
This is a full replacement for Android's standard network time
update implementation, which uses unauthentication SNTP (Simple
Network Time Protocol) with fallback to the cellular network when it's
not available (GNSS can also be used as a time source but is disabled
by default, and OEMs can choose the priority order). Network time
updates are security sensitive since certificate validation depends on
having an accurate time, but the standard NTP / SNTP protocols used
across most OSes have no authentication or encryption.
We plan to offer a toggle to use the standard functionality instead of
HTTPS-based time updates in order to blend in with other devices.
Network time can be disabled with the toggle at Settings ➔ System ➔ Date
& time ➔ Set time automatically. Unlike AOSP or the stock OS on the
supported devices, GrapheneOS stops making network time connections when using
network time is disabled rather than just not setting the clock based on it.
The time zone is still obtained directly via the time zone provided by the
mobile network (NITZ) when available which you can also disable by the "Set
time zone automatically" toggle.
-
Connectivity checks designed to mimic a web browser user agent are performed
by using HTTP and HTTPS to fetch standard URLs generating an HTTP 204 status
code. This is used to detect when internet connectivity is lost on a network,
which triggers fallback to other available networks if possible. These checks
are designed to detect and handle captive portals which substitute the
expected empty 204 response with their own web page.
The connectivity checks are done by performing an empty GET request to a
server returning an empty response with a 204 No Content response code. The
request uses a standard, frozen value for the user agent matching the same
value used by billions of other Android devices:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.32 Safari/537.36
No query / data is sent to the servers and the response is unused beyond
checking the response code.
Connectivity checks are performed for each network connection and
for VPN connections on top of those. This allows the OS to choose the
right underlying network for a VPN and to handle many types of captive
portals without the user turning off their VPN.
You can change the connectivity check URLs via the Settings ➔
Network & Internet ➔ Internet connectivity check setting.
At the moment, it can be toggled between the GrapheneOS servers
(default), the standard Google servers used by billions of other
Android devices or disabled.
By default, the GrapheneOS connectivity check servers are used via the
following URLs:
- HTTPS: https://connectivitycheck.grapheneos.network/generate_204
- HTTP: http://connectivitycheck.grapheneos.network/generate_204
- HTTP fallback: http://grapheneos.online/gen_204
- HTTP other fallback: http://grapheneos.online/generate_204
Changing this to the Standard (Google) mode will use the same URLs
used by AOSP and the stock OS along with the vast majority of other
devices, blending in with billions of other Android devices both with
and without Play services:
- HTTPS: https://www.google.com/generate_204
- HTTP: http://connectivitycheck.gstatic.com/generate_204
- HTTP fallback: http://www.google.com/gen_204
- HTTP other fallback: http://play.googleapis.com/generate_204
GrapheneOS also adds the ability to fully disable the connectivity
checks. This results in the OS no longer handling captive portals
itself, not falling back to other networks when some don't have
internet access and not being able to delay scheduled jobs depending
on internet access until it becomes available.
-
HTTPS connections are made to fetch
PSDS
information to assist with satellite based location. These are
static files and are downloaded automatically to improve location
resolution speed and accuracy. No query or data is sent to these
servers. These contain orbits and statuses of satellites, Earth
environmental data and time adjustment information.
On 6th and 7th generation Pixels (which use a Broadcom GNSS chip),
almanacs are downloaded from
https://broadcom.psds.grapheneos.org/lto2.dat,
https://broadcom.psds.grapheneos.org/rto.dat and
https://broadcom.psds.grapheneos.org/rtistatus.dat which are a cache
for Broadcom's data available at
https://gllto.glpals.com/7day/v5/latest/lto2.dat,
https://gllto.glpals.com/rto/v1/latest/rto.dat and
https://gllto.glpals.com/rtistatus4.dat. Alternatively, the standard
servers can be enabled in the Settings app which are
https://agnss.goog/lto2.dat, https://agnss.goog/rto.dat and
https://agnss.goog/rtistatus.dat providing a similar cache of
Broadcom's data currently (as of October 2022) hosted on GCP (Google
Cloud Platform).
On 4th and 5th generation Pixels (which use a Qualcomm baseband
providing cellular, Wi-Fi, Bluetooth and GNSS in separate sandboxes),
almanacs are downloaded from
https://qualcomm.psds.grapheneos.org/xtra3Mgrbeji.bin which is a cache
of Qualcomm's data. Alternatively, the standard servers can be enabled
in the Settings app which will use
https://path1.xtracloud.net/xtra3Mgrbeji.bin,
https://path2.xtracloud.net/xtra3Mgrbeji.bin and
https://path3.xtracloud.net/xtra3Mgrbeji.bin. GrapheneOS improves the
privacy of Qualcomm PSDS (XTRA) by removing the User-Agent header
normally containing an SoC serial number (unique hardware identifier),
random ID and information on the phone including manufacturer, brand
and model. We also always fetch the most complete XTRA database variant
(xtra3Mgrbeji.bin) instead of model/carrier/region dependent variants
to avoid leaking a small amount of information based on the database
variant.
Qualcomm Snapdragon SoC devices also fetch time via NTP for
xtra-daemon instead of using potentially incorrect OS time. We use
time.grapheneos.org when using the default GrapheneOS PSDS servers or
the standard time.xtracloud.net when using Qualcomm's servers. Stock
Pixel OS uses time.google.com but we follow Qualcomm's standard
settings to match other devices and to avoid the incompatible leap
second handling. These connections all go through the Owner VPN so it
isn't a real world fingerprinting issue.
-
Android devices launched with Android 8 or later provide support
for hardware-based attestation as part of the hardware keystore API.
Secure devices like Pixels provide both the traditional Trusted
Execution Environment (TrustZone) keystore and StrongBox keystore
based on a secure element, each providing attestation support. The
hardware-based attestation feature is a standard part of the Android
Open Source Project and are used to implement our Auditor app among
other things.
Initially, attestation signing keys were required to be batch keys
provisioned to at least 100k devices to avoid them being used as
unique identifiers. Unique attestation signing keys are an optional
feature only available to privileged system components. Recent devices
have replaced the batch and unique key system with remotely
provisioned signing keys. The device obtains encrypted keys from a
service to be decrypted by batch or unique keys inside the TEE and
optional secure element. The new system improves privacy and security
by using separate attestation signing keys for each app instead of
needing to balance privacy and security by sharing the same
attestation signing keys across a large batch of devices.
GrapheneOS uses https://remoteprovisioning.grapheneos.org/ by
default which is a private reverse proxy to the
https://remoteprovisioning.googleapis.com/ service. The service splits
up the implementation of provisioning to preserve privacy, and our
reverse proxy adds to that since it's unable to decrypt the
provisioned keys
A setting is added at Settings ➔ Network & Internet ➔
Attestation key provisioning server for switching to directly using
the Google service if you prefer.
A future device built to run GrapheneOS as the stock OS would be
able to have a GrapheneOS attestation root and GrapheneOS attestation
key provisioning service rather than a GrapheneOS proxy. A device
built to run another OS without Google certification would need their
own service and we'd need to support proxying to that service too.
-
A test query is done via DNS-over-TLS in the automatic and manually
enabled modes to detect if DNS-over-TLS is available. It won't happen
when DNS-over-TLS is disabled. For the automatic mode, it uses this to
determine if it should be using it and for the manual mode it uses it
to report an error. This DNS query is not used to make a connection to
the resulting resolved IP.
GrapheneOS queries the DNS resolver for
randomstring-dnsotls-ds.dnscheck.grapheneos.org
by default but switches to using the standard
randomstring-dnsotls-ds.metric.gstatic.com
when the HTTP(S) connectivity check mode is set to Standard (Google)
instead of the default GrapheneOS mode or Disabled mode to avoid
identifying itself as GrapheneOS to the DNS resolver. The DNS-over-TLS
test query will still happen with HTTP(S) connectivity checks disabled
but DNS-over-TLS can be disabled by disabling Private DNS.
The random string is used to bypass DNS caching to make sure the
DNS resolver works. It's generated with a cryptographically secure
random number generator (CSPRNG) for each request and therefore can't
leak any identifying info.
-
DNS resolution for other connections involving connections to the
network / user provided DNS resolvers
Other Vanadium browser connections are initiated by the user such as the
search engine (defaults to DuckDuckGo), websites and retrieving favicons for
your bookmarks and the frequent sites shown on the home page. We enable
connection and cache partitioning to keep connections separate between
different sites. There are a few parts of state partitioning still being
implemented including cookie partitioning which is currently in the testing
phase but causes too many compatibility issues to fully deploy it by default
without any exceptions like Brave's heuristics to disable it for cross-site
login flows, etc.
Unlike Chrome/Chromium, Vanadium WebView does not make connections beyond
those initiated by the app using it so there are no default connections from
apps using the WebView.
The previous section is an exhaustive list of all the default connections
made by a fresh GrapheneOS installation. Using a carrier, installing apps and
changing configuration can enable additional connections. This section aims to
list the cases which are not completely obvious to users. For example, if you
explicitly configure a Private DNS server, we don't need to explain here that
the OS will be connecting to that server.
Apps can list domains where they want to handle URLs instead of them being
handled by the browser. Domains officially associated with an app can add the
required metadata authorizing the app to automatically handle URLs which the
OS will fetch via HTTPS after installing the app to confirm if the app claims
to be authorized. See our usage guide
section on app link verification for more details such as how to block
these connections. The apps bundled with GrapheneOS don't require this and we
could hard-wire domains as verified if they did and we wanted to avoid more
default connections.
Most other connections made by the OS itself are made based on your chosen
carrier. The OS has a database of APN and other carrier configuration settings
which determines how this works by default. Normally, carriers can force their
configuration choices on users by making APNs read-only and disabling various
configuration options. GrapheneOS ignores this and always allows configuring
APNs, APN types, changing preferred network mode, toggling off 2G and using
tethering regardless of what the carrier wants. We leave the defaults chosen
by the carriers alone. For example, if you want tethering traffic treated
normally, you can remove the dun
APN type from your APN
configuration.
When you have both a cellular connection and Location enabled, control plane
and/or user plane (SUPL) A-GNSS is used in addition to PSDS to greatly reduce
the time needed for GNSS to obtain an initial location lock. These obtain
coarse location info from a server based on nearby cell towers. Control plane
A-GNSS is provided by the cellular connection itself and therefore doesn't
have any real privacy implications while SUPL connects to a server often not
provided by the carrier. Most A-GNSS services only accelerate obtaining a satellite-based
location and won't provide an estimate on their own. The carrier can choose a
SUPL server as part of their carrier configuration but most leave it at the
default of supl.google.com. By default, GrapheneOS overrides the
carrier/fallback SUPL server and uses the supl.grapheneos.org proxy. GrapheneOS adds a
toggle for configuring SUPL in Settings ➔ Location where you can choose
between the default supl.grapheneos.org proxy, the standard server
(carrier/fallback) or disabling it completely. GrapheneOS also disables
sending IMSI and phone number as part of SUPL. Pixels with a Qualcomm baseband
use it to provide both cellular and GNSS including both control plane and user
plane A-GNSS being implemented inside the baseband. For Qualcomm baseband
devices, SUPL is only enabled if the APN configuration for the carrier
includes supl
as an APN type. Pixels with a Samsung baseband have
a separate Broadcom GNSS chip without integration between them so SUPL is done
by the OS with regular networking (can use Wi-Fi and VPN) and SUPL is used
regardless of the carrier's APN type configuration. GrapheneOS upgrades the
Broadcom SUPL implementation to only using TLSv1.2 instead of using TLSv1.1
and older with TLSv1.2 disabled.
MMS, RCS, SMS over LTE, VVM (Visual Voicemail), VoLTE (carrier-based calls
on 4G and higher), VoNR (5G) and VoWi-Fi are largely implemented by the OS via
TCP/IP rather than by the cellular layer itself. This means there will be
connections by the OS to carrier servers instead of being handled by cellular.
GrapheneOS modifies carrier configuration so that toggles for disabling VoLTE,
VoNR and VoWi-Fi are always available. We plan to provide more toggles to
control these things in the future beyond making all the standard toggles
available.
GrapheneOS services follow the EFF's
privacy-friendly Do Not Track (DNT) policy for all users of our publicly available
services, not just those opting out of tracking via Do Not Track. Our policy is the
same with "DNT User" redefined as "user" to cover any user. This serves as a standard
privacy policy across all of our public services:
- attestation.app
- grapheneos.network
- grapheneos.online
- grapheneos.org
- grapheneos.social
- apps.grapheneos.org
- broadcom.psds.grapheneos.org
- qualcomm.psds.grapheneos.org
- discuss.grapheneos.org
- element.grapheneos.org
- mail.grapheneos.org
- matrix.grapheneos.org
- releases.grapheneos.org
- remoteprovisioning.grapheneos.org
- supl.grapheneos.org
- time.grapheneos.org
- update.vanadium.app
- dl.vanadium.app
Our implementation of the policy primarily consists of making sure our servers only
retain logs for 10 days. In practice, we follow much stricter privacy guidelines
than the rules laid out in the EFF policy. However, we don't want to define our own
complex, ad-hoc privacy policy rather than reusing a sensible one with serious thought
put into it by experts.
Our mail server (mail.grapheneos.org), Matrix server
(matrix.grapheneos.org), Element instance (element.grapheneos.org) and
Mastodon server (grapheneos.social) only provide accounts for GrapheneOS
project members so most functionality is outside the scope of what's relevant
to a public privacy policy.
The OS uses the network-provided DNS servers by default. Typically, dynamic
IP configuration is used to auto-configure the client on the network. IPv4 DNS
servers are obtained via DHCP and IPv6 DNS servers are obtained via RDNSS. For
a static IP configuration, the DNS servers are manually configured as part of
the static configuration.
A VPN provides a network layered on top of the underlying networks and the
OS uses the VPN-provided DNS servers for everything beyond resolving the IP
address of the VPN and performing network connectivity checks on each of the
underlying networks in addition to the VPN itself.
Using the network-provided DNS servers is the best way to blend in with
other users. Network and web sites can fingerprint and track users based on a
non-default DNS configuration. Our recommendation for general purpose usage is
to use the network-provided DNS servers.
In some broken or unusual network environments, the network could fail to
provide DNS servers as part of dynamic IP configuration. The OS has high
availability fallback DNS servers to handle this case. A network can fail to
provide DNS servers in order to fingerprint clients based on what they use as
the fallback so it's important for it to be consistent across each install.
GrapheneOS replaces Google Public DNS with
Cloudflare
DNS for the fallback DNS servers due to the superior privacy policy and
widespread usage including as the fallback DNS servers in other Android-based
operating systems. We're considering hosting our own servers and offering a
toggle for using the standard (Google) servers to blend in with other devices
similarly to how we handle the internet connectivity checks.
It isn't possible to directly override the DNS servers provided by the network via
DHCP. Instead, use the Private DNS feature in Settings ➔ Network & Internet ➔
Private DNS to set the hostname of a DNS-over-TLS server. It needs to have
a valid certificate such as a free certificate from Let's Encrypt. The OS will look up
the Private DNS hostname via the network provided DNS servers and will then force all
other DNS requests through the Private DNS server. Unlike an option to override the
network-provided DNS servers, this prevents the network from monitoring or tampering
with DNS requests/responses.
As an example, set the hostname to one.one.one.one
for Cloudflare DNS.
There are various other mainstream DNS-over-TLS options available including Quad9,
Google and AdGuard.
Configuring a static IP address for a network requires entering DNS servers
manually, but you should still use the Private DNS feature with it, and you shouldn't
misuse the static IP address option just to override the DNS servers.
VPN service apps can also provide their own DNS implementation and/or servers,
including an alternate implementation of encrypted DNS. Private DNS takes precedence
over VPN-provided DNS, since it's just the network-provided DNS.
Apps and web sites can detect the configured DNS servers by generating random
subdomains resolved by querying their authoritative DNS server. This can be used as
part of fingerprinting users. If you're using a VPN, you should consider using the
standard DNS service provided by the VPN service to avoid standing out from other
users.
By default, in the automatic mode, the Private DNS feature provides opportunistic
encryption by using DNS-over-TLS when supported by the DNS server IP addresses
provided by the network (DHCP) or the static IP configuration. Opportunistic
encryption provides protection against a passive listener, not an active attacker,
since they can force falling back to unencrypted DNS by blocking DNS-over-TLS. In the
automatic mode, certificate validation is not enforced, as it would provide no
additional security and would reduce the availability of opportunistic encryption.
When Private DNS is explicitly enabled, it uses authenticated encryption without a
fallback. The authentication is performed based on the hostname of the server, so it
isn't possible to provide an IP address. The OS will look up the hostname of the Private
DNS server via unencrypted DNS and then force all other DNS lookups via DNS-over-TLS
with the identity of the server authenticated as part of providing authenticated
encryption.
No, it only provides privacy for DNS resolution. Even authenticating DNS results
with DNSSEC does not protect other connections, unless the DNS records are part of the
system used to provide authenticated encryption, and DNS-over-TLS is not a substitute
for DNSSEC. If connections have authenticated encryption, they're secure even if DNS
resolution is hijacked by an attacker. If connections do not have authenticated
encryption, an attacker can listen in and tamper with them without hijacking DNS.
There are other ways to perform a MITM attack than DNS hijacking and internet routing
is fundamentally insecure. DNS-over-TLS may make a MITM harder for some attackers, but
don't count on it at all.
Private DNS only encrypts DNS, and an adversary monitoring connections can still
see the IP address at the other end of those connections. Many domains resolve to
ambiguous IP addresses, so encrypted DNS is part of what's required to take away a lot
of the information leaked to adversaries. However, TLS currently leaks domains via
SNI, so encrypted DNS is not yet accomplishing much. It's a forward looking feature
that will become more useful in the future. Using it is recommended, but it's not an
alternative to using Tor or a VPN.
VPNs can be configured under Settings ➔ Network & Internet ➔ VPN.
Support for the following protocols is included: IKEv2/IPSec MSCHAPv2,
IKEv2/IPSec PSK and IKEv2/IPSec RSA. Apps can also provide userspace VPN
implementations and the following open source apps are recommended: Orbot
(Tor), WireGuard and OpenVPN for Android.
VPN configurations created with the built-in support can be set as the
always-on VPN in the configuration panel. This will keep the VPN running,
reconnecting as necessary and will force all connections through them. An app
providing a VPN service can also be set as the always-on VPN via the entry in
the Settings page. For app-based VPN implementations, there's also an
additional "Block connections without VPN" toggle which is needed to prevent
leaks when the app's VPN service isn't running.
Apps cannot monitor network connections unless they're made into the active VPN
service by the user. Apps cannot normally access network stats and cannot directly
request access to them. However, app-based stats can be explicitly granted by users as
part of access to app usage stats in Settings ➔ Apps ➔ Special app access ➔ Usage
access.
This was previously part of the GrapheneOS privacy improvements, but became a
standard Android feature with Android 10.
Yes, GrapheneOS inherits the deeply integrated firewall from the Android
Open Source Project, which is used to implement portions of the security model
and various other features. The GrapheneOS project historically made various
improvements to the firewall but over time most of these changes have been
integrated upstream or became irrelevant.
GrapheneOS adds a user-facing Network permission toggle providing a robust
way to deny both direct and indirect network access to applications. It builds
upon the standard non-user-facing INTERNET permission, so it's already fully
adopted by the app ecosystem. Revoking the permission denies indirect access
via OS components and apps enforcing the INTERNET permission, such as
DownloadManager. Direct access is denied by blocking low-level network socket
access. A packet-based firewall would only block direct access so our approach
is much more complete. Additionally, GrapheneOS pretends that the Network is
down for most APIs when the Network permission is disabled. For example, it
won't run scheduled jobs depending internet availability and most APIs for
checking the state of the network will report it as down and internet access
as unavailable. This means apps won't try to keep trying to access the
internet and draining battery because they'll treat it the way they do when
internet access is genuinely unavailable.
The recommended approach to system-wide ad-blocking is setting up
domain-based ad-blocking as part of DNS resolution. You can do this by
choosing a Private DNS (DNS-over-TLS) server with
support for blocking ad domains. As an example, AdGuard DNS can be used by
setting dns.adguard-dns.com
as the Private DNS domain. This feature
used to be included by the project many years ago, but it needs to be
reimplemented, and it's a low priority feature depending on contributors
stepping up to work on it.
Apps and web sites can detect that ad-blocking is being used and can
determine what's being blocked. This can be used as part of fingerprinting
users. Using a widely used service like AdGuard with a standard block list is
much less of an issue than a custom set of subscriptions / rules, but it still
stands out compared to the default of not doing it.
Content filtering apps are fully compatible with GrapheneOS, but they have serious
drawbacks and are not recommended. These apps use the VPN service feature to route
traffic through themselves to perform filtering.
The approach of intercepting traffic is inherently incompatible with encryption
from the client to the server. The AdGuard app works around encryption by supporting
optional
HTTPS interception by
having the user trust a local certificate authority, which is a security risk and
weakens HTTPS security even if their implementation is flawless (which they openly
acknowledge in their documentation, although it understates the risks). It also can't
intercept connections using certificate pinning, with the exception of browsers which
go out of the way to allow overriding pinning with locally added certificate
authorities. Many of these apps only provide domain-based filtering, unlike the deeper
filtering by AdGuard, but they're still impacted by encryption due to Private DNS
(DNS-over-TLS) and require disabling the feature. They could provide their own
DNS-over-TLS resolver to avoid losing the feature, but few of the developers care
enough to do that.
Using the VPN service to provide something other than a VPN also means that these
apps need to provide an actual VPN implementation or a way to forward to apps
providing one, and very few have bothered to implement this. NetGuard is an
example of an app implementing SOCKS5 forwarding, which can be used to forward to apps
like Orbot (Tor).
Yes, the baseband is isolated on all of the officially supported devices. Memory
access is partitioned by the IOMMU and limited to internal memory and memory shared
by the driver implementations. The baseband on the officially supported devices with a
Qualcomm SoC implements Wi-Fi and Bluetooth as internal sandboxed processes rather
than having a separate baseband for those like earlier devices.
Earlier generation devices we used to support prior to Pixels had Wi-Fi + Bluetooth
implemented on a separate SoC. This was not properly contained by the stock OS and we
put substantial work into addressing that problem. However, that work has been
obsoleted now that Wi-Fi and Bluetooth are provided by the SoC on the officially
supported devices.
A component being on a separate chip is orthogonal to whether it's isolated. In
order to be isolated, the drivers need to treat it as untrusted. If it has DMA access,
that needs to be contained via IOMMU and the driver needs to treat the shared memory
as untrusted, as it would do with data received another way. There's a lot of attack
surface between the baseband and the kernel/userspace software stack connected to it.
OS security is very relevant to containing hardware components including the radios and
the vast majority of the attack surface is in software. The OS relies upon the
hardware and firmware to be able to contain components but ends up being primarily
responsible for it due to control over the configuration of shared memory and the
complexity of the interface and the OS side implementation.
The mobile Atheros Wi-Fi driver/firmware is primarily a SoftMAC implementation with
the vast majority of the complexity in the driver rather than the firmware. The fully
functional driver is massive and the firmware is quite small. Unfortunately, since the
Linux kernel is monolithic and has no internal security boundaries, the attack surface
is problematic and a HardMAC implementation with most complexity in the isolated
firmware could be better than the status quo. An isolated driver would be ideal.


JSON Editor supports these popular CSS frameworks:
JSON Editor supports these popular icon libraries:


This cost is {{cost|currency}}.
This tax is {{tax*0.15|currency}}.
This total is {{total|currency}}. Add
Your running total is {{final_bill|currency}}.


i'm eid jamal sukariah a mechanical engineer and web developer passionate about training and working for a reputable company. And learning from those with experience and developing self-skills.
| experience | courses |
|---|---|
| Medical supplies | full-stack web development |
| Boilers maintenance and operation | HAP program |
| Fundamentals of Digital Marketing |
- Boilers maintenance and operation
- Medical supplies
- graphic designer
my experience
- HAP program
- Fundamentals of Digital Marketing
- full-stack web development
the courses i toke
- the shawshank redemption
- the godfather
- Memento
- seven
- inception
- gladiator
- the lion king
- the dark knight
- pulp fiction
- avatar


OUT
- IN
- the type of the second link in the functional chainpublic class Subscription<IN,OUT> extends java.lang.Object implements IReactiveTarget<IN>, IReactiveSource<OUT>
NOTE: Because there _may_ exist a possibility of multiple fire events racing each other on different threads, it is important that the functions in the reactive chain are idempotent and stateless.
Subscription
s are both an IReactiveTarget
and
IReactiveSource
.
TODO Add setFireEveryValue(true) option to queue up and fire all states one by one. If inOrderExecutor, this fire will be FIFO sequential, otherwise concurrent
| Modifier and Type | Field and Description |
|---|---|
protected IOnErrorAction |
onError |
protected IActionOneR<IN,OUT> |
onFireAction |
protected ImmutableValue<java.lang.String> |
origin |
protected java.util.concurrent.CopyOnWriteArrayList<AltWeakReference<IReactiveTarget<OUT>>> |
reactiveTargets |
protected IThreadType |
threadType |
| Constructor and Description |
|---|
Subscription(java.lang.String name,
IReactiveSource<IN> upchainReactiveSource,
IThreadType threadType,
IActionOneR<IN,OUT> onFireAction,
IOnErrorAction onError)
Create a new default implementation of a reactive functional chain link
|
| Modifier and Type | Method and Description |
|---|---|
void |
fire(IN in)
An upchain
IReactiveSource is notifying us
of a new input value to process. |
void |
fireNext(IN in)
Same as
IReactiveTarget.fire(Object) however this is queued LIFO for more immediate execution. |
java.lang.String |
getName()
A descriptive name to assist the developer with debugging
|
protected ImmutableValue<java.lang.String> |
getOrigin() |
protected boolean |
searchReactiveTargets(IReactiveTarget<OUT> searchItem,
IActionOne<IReactiveTarget<OUT>> actionIfFound)
Search downstream targets and do
actionIfFound if you find the one specified |
IReactiveSource<OUT> |
split(IReactiveTarget<OUT> reactiveTarget)
Attach a downstream
.subscribe() like IReactiveSource.split(IReactiveTarget)
as a WeakReference
for automatic down-chain IReactiveSource.unsubscribe(String, IReactiveTarget) on garbage collect of reactive chain leaf node. |
IReactiveSource<OUT> |
subscribe(IAction<OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
IReactiveSource<OUT> |
subscribe(IActionOne<OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
<DOWNCHAIN_OUT> |
subscribe(IActionR<OUT,DOWNCHAIN_OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
IReactiveSource<OUT> |
subscribe(IReactiveTarget<OUT> reactiveTarget)
Add an onFireAction as a new branch down-chain from this node.
|
IReactiveSource<OUT> |
subscribe(IThreadType threadType,
IAction<OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
IReactiveSource<OUT> |
subscribe(IThreadType threadType,
IActionOne<OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
<DOWNCHAIN_OUT> |
subscribe(IThreadType threadType,
IActionR<OUT,DOWNCHAIN_OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
<DOWNCHAIN_OUT> |
subscribeMap(IActionOneR<OUT,DOWNCHAIN_OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
<DOWNCHAIN_OUT> |
subscribeMap(IThreadType threadType,
IActionOneR<OUT,DOWNCHAIN_OUT> action)
Add an onFireAction as a new branch down-chain from this node.
|
void |
subscribeSource(java.lang.String reason,
IReactiveSource<IN> reactiveSource)
Notification that an
IReactiveSource will start sending updates
This allows the target which is responsible for holding a strong reference to the source to
prevent it from being garbage collected until all targets of a given source go out of scope and
are themselves garbage collected. |
boolean |
unsubscribe(java.lang.String reason,
IReactiveTarget<OUT> reactiveTarget)
Remove a down-chain branch from the reactive function tree at this node
|
void |
unsubscribeAll(java.lang.String reason)
Remove all down-chain branches from this node of the reactive function tree
|
void |
unsubscribeAllSources(java.lang.String reason)
Remove all up-chain branches from this node of the reactive function tree
|
void |
unsubscribeSource(java.lang.String reason,
IReactiveSource<IN> reactiveSource)
Notification that an
IReactiveSource will no longer send updates
Since this target is responsible for holding a reference to the source to keep it from
being garbage collected, this target can not forget the source and, if not used elsewhere, it can be garbage collected. |
protected final IThreadType threadType
protected final IOnErrorAction onError
protected final java.util.concurrent.CopyOnWriteArrayList<AltWeakReference<IReactiveTarget<OUT>>> reactiveTargets
protected final ImmutableValue<java.lang.String> origin
protected final IActionOneR<IN,OUT> onFireAction
public Subscription(java.lang.String name, IReactiveSource<IN> upchainReactiveSource, IThreadType threadType, IActionOneR<IN,OUT> onFireAction, IOnErrorAction onError)
If there are multiple down-chain targets attached to this node, it will concurrently fire all down-chain branches.
name
- the descriptive debug name of this subscriptionupchainReactiveSource
- threadType
- the default thread group on which this subscription firesonFireAction
- Because there _may_ exist a possibility of multiple fire events racing each other on different
threads, it is important that the onFireAction functions in the reactive chain are idempotent and stateless. Further analysis is needed, but be cautious.onError
- protected ImmutableValue<java.lang.String> getOrigin()
public java.lang.String getName()
INamed
public void subscribeSource(java.lang.String reason, IReactiveSource<IN> reactiveSource)
IReactiveTarget
IReactiveSource
will start sending updates
This allows the target which is responsible for holding a strong reference to the source to
prevent it from being garbage collected until all targets of a given source go out of scope and
are themselves garbage collected.
You may manually speed this process by calling IReactiveTarget.unsubscribeSource(String, IReactiveSource)
,
however if you choose not to or forget to do so, it will be taken care of for you fairly soon.subscribeSource
in interface IReactiveTarget<IN>
public void unsubscribeSource(java.lang.String reason, IReactiveSource<IN> reactiveSource)
IReactiveTarget
IReactiveSource
will no longer send updates
Since this target is responsible for holding a reference to the source to keep it from
being garbage collected, this target can not forget the source and, if not used elsewhere, it can be garbage collected.unsubscribeSource
in interface IReactiveTarget<IN>
protected final boolean searchReactiveTargets(IReactiveTarget<OUT> searchItem, IActionOne<IReactiveTarget<OUT>> actionIfFound) throws java.lang.Exception
actionIfFound
if you find the one specifiedsearchItem
- the target to be located in the subscribed targets listactionIfFound
- an action to perform on that target if foundtrue
if found and action performedjava.lang.Exception
public void fire(IN in)
IReactiveTarget
IReactiveSource
is notifying us
of a new input value to process.
 They are
called for you when this is an input or state change, for example by
ReactiveValue.set(Object)
Nodes within a reactive chain may choose to be stateless such as
Subscription
.
Nodes at the leaf of a reactive chain will typically retain this value as state, for example
(ReactiveValue
).
They may also choose to otherwise create a stateful side effect with the value received. The recommended practice is to not create such side effects except in the leaf node(s) at the end of chain branches. If you violate this rule, be warned you tend to end up with a hairy memory management and partially-completed-stateful-logic-before-exception error correction mess.
If you would like to unlink this object when the fire operation results in an error, you must
do so in an .onError()
statement lower down in the chain you wish to trigger
such an action.
fire
in interface IReactiveTarget<IN>
in
- The value from the previous link in the reactive chain.public void fireNext(IN in)
IReactiveTarget
IReactiveTarget.fire(Object)
however this is queued LIFO for more immediate execution.
You do not generally call this directly. Chains call this for you. It is called instead of IReactiveTarget.fire(Object)
mid-chain to reduce
work in progress and complete the task tree is an depth-first manner. This reduces the latency of
individual chains once execution starts. It also decreases the peak memory load by more rapidly
flushing intermediate values to the leaf node side effects of the chain.fireNext
in interface IReactiveTarget<IN>
public boolean unsubscribe(java.lang.String reason, IReactiveTarget<OUT> reactiveTarget)
IReactiveSource
unsubscribe
in interface IReactiveSource<OUT>
true
if the branch was found and removedpublic void unsubscribeAllSources(java.lang.String reason)
IReactiveTarget
unsubscribeAllSources
in interface IReactiveTarget<IN>
public void unsubscribeAll(java.lang.String reason)
IReactiveSource
unsubscribeAll
in interface IReactiveSource<OUT>
public IReactiveSource<OUT> split(IReactiveTarget<OUT> reactiveTarget)
IReactiveSource
.subscribe()
like IReactiveSource.split(IReactiveTarget)
as a WeakReference
for automatic down-chain IReactiveSource.unsubscribe(String, IReactiveTarget)
on garbage collect of reactive chain leaf node.split
in interface IReactiveSource<OUT>
public IReactiveSource<OUT> subscribe(IAction<OUT> action)
IReactiveSource
It will execute on the same IThreadType
as this node and may be called synchronously.
If this onFireAction
is a lambda with closure references to a surrounding Object
context, subscribe the onFireAction will automatically IReactiveSource.unsubscribe(String, IReactiveTarget)
when the surrounding
context is garbage collected and any down-chain IReactiveTarget
is garbage collected.
subscribe
in interface IReactiveSource<OUT>
public IReactiveSource<OUT> subscribe(IThreadType threadType, IAction<OUT> action)
IReactiveSource
subscribe
in interface IReactiveSource<OUT>
threadType
- The onFireAction will be called asynchronously unless the this is same IThreadType
as this (upchain) node in the reactive function tree.public IReactiveSource<OUT> subscribe(IActionOne<OUT> action)
IReactiveSource
It will execute on the same IThreadType
as this node and may be called synchronously.
If this onFireAction
is a lambda with closure references to a surrounding Object
context, subscribe the onFireAction will automatically IReactiveSource.unsubscribe(String, IReactiveTarget)
when the surrounding
context is garbage collected and any down-chain IReactiveTarget
is garbage collected.
subscribe
in interface IReactiveSource<OUT>
public IReactiveSource<OUT> subscribe(IThreadType threadType, IActionOne<OUT> action)
IReactiveSource
subscribe
in interface IReactiveSource<OUT>
threadType
- The onFireAction will be called asynchronously unless the this is same IThreadType
as this (upchain) node in the reactive function tree.public <DOWNCHAIN_OUT> IReactiveSource<DOWNCHAIN_OUT> subscribeMap(IActionOneR<OUT,DOWNCHAIN_OUT> action)
IReactiveSource
It will execute on the same IThreadType
as this node and may be called synchronously.
If this onFireAction
is a lambda with closure references to a surrounding Object
context, subscribe the onFireAction will automatically IReactiveSource.unsubscribe(String, IReactiveTarget)
when the surrounding
context is garbage collected and any down-chain IReactiveTarget
is garbage collected.
subscribeMap
in interface IReactiveSource<OUT>
public <DOWNCHAIN_OUT> IReactiveSource<DOWNCHAIN_OUT> subscribeMap(IThreadType threadType, IActionOneR<OUT,DOWNCHAIN_OUT> action)
IReactiveSource
subscribeMap
in interface IReactiveSource<OUT>
threadType
- The onFireAction will be called asynchronously unless the this is same IThreadType
as this (upchain) node in the reactive function tree.public IReactiveSource<OUT> subscribe(IReactiveTarget<OUT> reactiveTarget)
IReactiveSource
It will execute on the same IThreadType
as this node and may be called synchronously.
subscribe
in interface IReactiveSource<OUT>
public <DOWNCHAIN_OUT> IReactiveSource<DOWNCHAIN_OUT> subscribe(IActionR<OUT,DOWNCHAIN_OUT> action)
IReactiveSource
subscribe
in interface IReactiveSource<OUT>
public <DOWNCHAIN_OUT> IReactiveSource<DOWNCHAIN_OUT> subscribe(IThreadType threadType, IActionR<OUT,DOWNCHAIN_OUT> action)
IReactiveSource
subscribe
in interface IReactiveSource<OUT>