Skip to content

Implement support for out of band OTAs via file picker - #127

Open
flawedworld wants to merge 1 commit into
GrapheneOS:17from
flawedworld:17
Open

Implement support for out of band OTAs via file picker#127
flawedworld wants to merge 1 commit into
GrapheneOS:17from
flawedworld:17

Conversation

@flawedworld

Copy link
Copy Markdown
Member

No description provided.

@flawedworld
flawedworld marked this pull request as ready for review June 23, 2026 23:33
@flawedworld
flawedworld marked this pull request as draft June 23, 2026 23:38
@flawedworld
flawedworld marked this pull request as ready for review June 23, 2026 23:43
@flawedworld

Copy link
Copy Markdown
Member Author

I tested the file picker path on mustang and things seem to work fine there.

@flawedworld flawedworld changed the title Implement support for out of band OTAs via file picker or ADB Implement support for out of band OTAs via file picker Jun 23, 2026
Comment thread res/values/strings.xml
<string name="install_from_file_summary">Manually choose an OTA update package to verify and install</string>
<string name="install_from_file_confirm_title">Confirm it\'s you</string>
<string name="install_from_file_confirm_description">Authenticate to install an update from a file</string>
<string name="install_from_file_no_credential">Set a device PIN, pattern or password to install updates from a file</string>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GrapheneOS doesn't support pattern

}

// Manually install an OTA from a file chosen with the system file picker. This is gated behind
// a confirmation of the owner's device credential (PIN / password / pattern) so it cannot be

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GrapheneOS doesn't support pattern

Comment on lines +135 to +137
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Subclass chain:

  1. Settings
  2. androidx.fragment.app.FragmentActivity
  3. androidx.activity.ComponentActivity
  4. android.app.Activity

onActivityResult is deprecated in androidx.activity.ComponentActivity. The recommendation is to use Activity Result APIs (ActivityResultLauncher)

(Note that onActivityResult is not deprecated in android.app.Activity or FragmentActivity)

Comment on lines +117 to +120
// Returns null when no device credential is set, which is the only state we need to reject.
final Intent intent = getSystemService(KeyguardManager.class).createConfirmDeviceCredentialIntent(
getString(R.string.install_from_file_confirm_title),
getString(R.string.install_from_file_confirm_description));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KeyguardManager#createConfirmDeviceCredentialIntent is deprecated

Comment on lines +180 to +183
requirePreference(KEY_INSTALL_FROM_FILE).setOnPreferenceClickListener(pref -> {
((Settings) requireActivity()).startInstallFromFile();
return true;
});

@inthewaves inthewaves Aug 19, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should prevent OTA from being picked while update_engine is actively installing, and also e.g. the existing manual network action checks KEY_WAITING_FOR_REBOOT before starting its service

Comment on lines 455 to 459
} catch (GeneralSecurityException | IOException | ServiceSpecificException e) {
Log.e(TAG, "failed to download and install update", e);
notificationHandler.showFailureNotification(e.getMessage());
mUpdating = false;
if (serviceIsUserInitiated) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This failure notification does not account for the local case

When a local copy, verification, or install fails, the generic notification text says the package came from the server, that it will be downloaded again, or that Updater will retry, etc. It should be using error notification strings saying stuff like package was not installed and must be chosen again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants