Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

add optional installation of play apps into work profile #559

Closed
wants to merge 312 commits into from

Conversation

mkg20001
Copy link

@mkg20001 mkg20001 commented Jul 31, 2024

Just a rudimentary PR for now (code works already). Waiting for feedback if change is wanted. with GrapheneOS/os-issue-tracker#1821 arround I'm just assuming yes

testing instructions: https://github.com/GrapheneOS/platform_frameworks_base/pull/559#issuecomment-2267344940

Problem:

Currently when using any DPC app (like Google Device Policy or others) that uses play services in any way it expects it to be present in the newly created work profile, as this is the case on phones with un-sandboxed-gapps.

Solution:

This can be solved with installing the play services into the work profile.
Because this needs to happen at the earliest possible moments in order for the DPC app to do it's job properly (mainly Google Device Policy, prob others aswell), this needs to be part of the profile creation itself.


It is planned to make this optional and disabled by default, as not everyone needs that behaviour. Automatically detects if DPC app uses play services.

The UI toggle would be added in GmsCompat.

Not sure whether to put it's value into GmsCompat, since I'm not sure how easy it is to access that value from DevicePolicyManagerService.

@mkg20001
Copy link
Author

mkg20001 commented Jul 31, 2024

So I tried setting up a regular google work account

There are some other issues specifically with that:

  • when play store is installed, it needs to be given the permission to install unknown apps at install time. as otherwise the DPC might disallow installing third-party apps and therefore block the play store from functioning
    • This should be doable as part of the app installation in device policy
    • added permission grant via app ops service
  • when adding the account first as regular user, play uses some special intent to start deployment and/or copy the authorization into the work profile. that intent breaks as it requires a special permission.
    • Maybe fixable via GmsCompat magic
    • This isn't really an issue as setup can still be completed, it just requires to login in twice

My profile is also stuck in a weird state as I'm using an emulator (as I don't have a test device) and the work profile needs to be custom-rom-certified seperatly from the main profile which breaks the setup (google.com/android/uncertified)

@mkg20001
Copy link
Author

mkg20001 commented Aug 1, 2024

I got myself a dev phone, it should arrive next week. Then I can test this properly.

@@ -581,7 +581,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

private static final String ATTRIBUTION_TAG = "DevicePolicyManagerService";

static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE
static final boolean VERBOSE_LOG = true; // DO NOT SUBMIT WITH TRUE
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to remove this change and squash the newer changes once cleaned up.

@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

Ok so if DPC blocks "allow from source" it also blocks all app installs, even from play store as that isn't a system app. There would need to be a patch for that.

@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

That is now fixed aswell

@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

What should be done when play in work profile tries to downgrade app? Currenty it fails but it could also be made to just clone the existing version of the app into work profile silently

@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

Testing with Google managed work profile:

I made a test google workspace for testing this, if you need an account for testing I can give you access

  • open app with google account support (drive, gmail, etc) that is NOT play store

  • add work account: click profile (top right) -> "add another account"

  • will crash after sign-in, then return to app

  • wait. if nothing happens check if the work account is selected in account chooser (top right) and select

  • asks for android device policy to be installed, install

  • will prompt to create work profile, click accept & continue

  • for emulator:

    • run: adb shell 'sqlite3 /data/user/$(pm list users | grep Work | grep -o "[0-9]*" | head -n 1)/*/*/gservices.db "select * from main where name = \"android_id\";"'
    • if command doesn't work wait
    • go to google.com/android/uncertified, add id
    • click on work profile notification to continue setup if you get a "device not certified" error
  • click next in work profile setup

  • will now ask to login again, do it

  • will now say to allow device, if necesarry, for the google workspace (ask your company helpdesk)

    • DO NOT REBOOT DURING THIS IT BREAKS SETUP
    • use ":" menu -> sync policies to check if authorized
    • use notification to go back to work profile setup
  • after everything is done prompt should auto-close and work account should be gone from user profile

last steps:

  • enable notifications for play in work profile (see notifications from GmsCompat with work icon)
  • open play and manually confirm 1) play store self-update 2) all the installs for work apps
  • if provisioning apps (first install of everything) doesnt start grant contacts permission

@quh4gko8 quh4gko8 requested a review from muhomorr August 4, 2024 05:59
@mkg20001 mkg20001 force-pushed the work-profile-gapps branch from f048d35 to 5950772 Compare August 4, 2024 07:14
@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

@flawedworld As requested the crash from setup:
Error in Google Play services 370b41359e04.txt

@flawedworld
Copy link
Contributor

This can maybe be shimmed in GmsCompat.

@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

There is also the non-privileged version of this intent, which is what shelter app uses. I think it's mostly the same except the user needs to confirm it. It could be made to use that instead.

@mkg20001
Copy link
Author

mkg20001 commented Aug 4, 2024

Setup video

peekOJ5GR2.mp4

@muhomorr
Copy link
Contributor

muhomorr commented Aug 6, 2024

I think this has to be addressed in a different way.

Work profile manager has to install the Google Play trio (GSF, GmsCore, Play Store) itself, it can be made to do so as part of work profile creation. DISALLOW_INSTALL_UNKNOWN_SOURCES issue can be fixed by adding a device policy API for allowlisting specific third-party package installers and making the work profile manager use this API to allowlist the Play Store.

@mkg20001
Copy link
Author

mkg20001 commented Aug 6, 2024

DISALLOW_INSTALL_UNKNOWN_SOURCES issue can be fixed by adding a device policy API for allowlisting specific third-party package installers and making the work profile manager use this API to allowlist the Play Store.

Makes sense, will do

Work profile manager has to install the Google Play trio (GSF, GmsCore, Play Store) itself, it can be made to do so as part of work profile creation.

What do you mean by "Work profile manager"? DevicePolicyManagerService or some other part? DevicePolicyManagerService currently just copies the package over with installPackageAsExistingUser, so you want it to instead also install play services if they are not already installed?

@muhomorr
Copy link
Contributor

muhomorr commented Aug 6, 2024

By "work profile manager" I mean the app that creates and manages the work profile. It has permission to install apps from other users into work profile without confirmation.

@mkg20001
Copy link
Author

mkg20001 commented Aug 6, 2024

Work profile manager has to install the Google Play trio (GSF, GmsCore, Play Store) itself, it can be made to do so as part of work profile creation

That is you are saying that all the apps that create work profiles will now need to acount for GOS not delivering play store as system app and having to install it afterwards? They won't. Even if we patch them ourselves similarly to play store, there are countless apps (not just the one from google), it will be easier to let the user decide to install play store during profile creation. Patching all of them is just not realistic.

I already have working code for installing play store into work profile, I will make it a prompt for installing it during work profile creation and add a permission that will be granted by that code to play store (so I don't need to skip checks for allow_unknown_sources). Edit: I can make the permission available to any app in device profile aswell.

Edit: And I understand your concern as to not provide anything special for play store. But unless play store as non-system-app is officially a thing, I don't think work profile manager apps can be required to account for it not being a system app. We're not giving google any special permissions either way.

@mkg20001
Copy link
Author

mkg20001 commented Aug 6, 2024

Just so I get it: INSTALL_PACKAGES is not something we should grant to play store, even in work profile and therefore can only use REQUEST_INSTALL_PACKAGES? Correct? Or not?

@thestinger thestinger force-pushed the 14 branch 2 times, most recently from af7c305 to ebb62a9 Compare August 6, 2024 22:01
@mkg20001 mkg20001 force-pushed the work-profile-gapps branch 2 times, most recently from 0e557ed to 3a7d281 Compare August 7, 2024 02:25
@mkg20001
Copy link
Author

mkg20001 commented Aug 7, 2024

I've rebased the changes against latest gos. Also please don't just force push this branch while I'm working on it.

Currently build may be broken as I'm just tossing commits in here for rebasing, etc. I will make a clean history once the major changes are in place.

@thestinger
Copy link
Contributor

GrapheneOS is now based on the August release of the Android Open Source Project and was rebased onto it. It's how this always works to keep the project at all maintainable and sustainable. Merging in all the releases would be horrific particularly for quarterly and yearly releases. Keeping it clean leading up to those is incredibly important for moving quickly. We can't stop porting to new releases and preparing for upcoming ones because someone has a PR open. Android 15 is coming soon and there will be major rebases to prepare for it soon.

@muhomorr
Copy link
Contributor

muhomorr commented Aug 7, 2024

That is you are saying that all the apps that create work profiles will now need to acount for GOS not delivering play store as system app and having to install it afterwards?

This is not what I meant. By "work profile manager can be made to do so as part of work profile creation"
I meant that it can be forced to do so by the OS, without any cooperation from the work profile manager app.

Even if we patch them ourselves similarly to play store

GSF, Play services, Play Store APKs are not modified in any way on GrapheneOS.

Patching all of them is just not realistic.

There are reliable ways to detect work profile manager apps attempting to create a work profile,
and a reliable way to detect whether an app depends on Play services, there's a marker in AndroidManifest
that is added by Play services client library.

Previously, ACCESS_KEYGUARD_SECURE_STORAGE permission was enough to check that.

Presence of duress password is intended to be unknown unless the owner credential is provided. This
was enforced in the UI layer (Settings app) already, but could be bypassed through UI bugs, such
as the recently patched predictive back gesture bug:
GrapheneOS/platform_packages_apps_Settings@e6ac6fa
@mkg20001
Copy link
Author

@thestinger I didn't get what the force push message said at first, I now realize that it's just the 14 branch in main repo, so it's fine. Lol.

@mkg20001 mkg20001 force-pushed the work-profile-gapps branch 3 times, most recently from 4b859ae to 231f174 Compare August 13, 2024 14:53
@mkg20001
Copy link
Author

This is ready for another round of review.

@mkg20001 mkg20001 force-pushed the work-profile-gapps branch from 231f174 to f5d4523 Compare August 13, 2024 16:14
@muhomorr
Copy link
Contributor

This PR is still far from using the approach that I've asked for above.

@mkg20001
Copy link
Author

This PR is still far from using the approach that I've asked for above.

What's missing? What woud you like to have changed?

@muhomorr
Copy link
Contributor

@mkg20001
Copy link
Author

mkg20001 commented Aug 15, 2024

Work profile manager has to install the Google Play trio (GSF, GmsCore, Play Store) itself, it can be made to do so as part of work profile creation

I do not understand what do you mean by "work profile manager has to do it"

How do I make work profile manager do that? Patch? Add hook somewhere? How/Where?

And how is it better to the current method of just doing that as part of DevicePolicyManagerService itself?

DISALLOW_INSTALL_UNKNOWN_SOURCES issue can be fixed by adding a device policy API for allowlisting specific third-party package installers and making the work profile manager use this API to allowlist the Play Store.

So you're looking for something like, say, those functions in DevicePolicyManager? Or is there a nicer way without making 3 new functions?

@requirepermission(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS)
setTrustedSource(packageName, userId) -> void

@requirepermission(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS)
unsetTrustedSource(packageName, userId) -> void

isTrustedSource(packageName, userId) -> bool

Also where would I store the value? Set it per app via appops + USER_TRUSTED_SOURCE permission or is there a better way?

Directory can be removed by the time listFiles() is called, which makes it return null. Null can
also be returned due to an I/O error.
@mkg20001 mkg20001 force-pushed the work-profile-gapps branch from f5d4523 to 9c20757 Compare August 19, 2024 12:13
@muhomorr
Copy link
Contributor

How do I make work profile manager do that? Patch? Add hook somewhere? How/Where?

There are several approaches used by the GmsCompat layer to achieve this. It's hard to tell which one would fit best without looking into this in depth.

And how is it better to the current method of just doing that as part of DevicePolicyManagerService itself?

DevicePolicyManagerService runs inside system_server, which is a highly privileged system component. Introducing a bug there would be a lot more serious than introducing a bug in an unprivileged work profile manager app process. Moreover, system_server internal APIs change often, while the public work profile manager app APIs are very stable, which helps a lot in maintaining such changes.

So you're looking for something like, say, those functions in DevicePolicyManager? Or is there a nicer way without making 3 new functions?

At a minimum, APK certificate digests should be specified and checked.

Also where would I store the value? Set it per app via appops + USER_TRUSTED_SOURCE permission or is there a better way?

It's hard to say which approach to use without researching this in-depth. I currently don't have enough time for that.

@mkg20001
Copy link
Author

Thanks for the response! Yes, makes sense to put it outside of DevicePolicyManagerService.

Do you happen to know somebody in or outside the team that I can ask more in-depth questions that has time for that? Or do you have any guides about android / graphene platform development you could recommend? Or should I just stick to asking in the Development channel?

@muhomorr
Copy link
Contributor

Do you happen to know somebody in or outside the team that I can ask more in-depth questions that has time for that?

No.

Or do you have any guides about android / graphene platform development you could recommend?

I can recommend https://source.android.com/ and reading the code itself.

muhomorr and others added 5 commits August 23, 2024 05:41
For matching in maybeInstallPlay in DevicePolicyManagerService
…triction

This permission is supposed to be granted to apps that are installed in 
a work profile and should be exempt from the DISALLOW_UNKNOWN_SOURCES 
restriction that can be set via device policy
When setting up a work profile, GmsCore tries to install Android Device 
Policy apk

For this to work REQUEST_INSTALL_PACKAGES permission needs to be in 
manifest
Currently when using any DPC app (like Google Device Policy or others)
that uses play services in any way it expects it to be present in the
newly created work profile, as this is the case on phones with
un-sandboxed-gapps.

That's currently broken on GOS due to play apps not being global here.

This can be solved with installing the play services into the work
profile.

We automatically detect if the app needs play services and install them
into the work profile alongside it.

Because this needs to happen at the earliest possible moments in order
for the DPC app to do it's job properly (mainly Google Device Policy,
likely others aswell), this needs to be part of the profile creation
itself.
@mkg20001 mkg20001 force-pushed the work-profile-gapps branch from 9c20757 to b6d9f9e Compare August 24, 2024 21:36
@turbamulta
Copy link

Thank you for the effort trying to get managed work profiles to work. Following.

@mkg20001
Copy link
Author

Fyi I'm currently busy and will continue this work after android 15 release, as I suspect there might be major changes. If anyone has any hints for me on how to best implement this, just comment.

@mkg20001
Copy link
Author

new pr in new repo: GrapheneOS/platform_frameworks_base#4

@thestinger thestinger closed this Sep 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.