Skip to content

Conversation

@mkg20001
Copy link

@mkg20001 mkg20001 commented Mar 21, 2025

Currently when creating a work profile with a DPC app that requires play services, the DPC app expects play services to also exist on the work profile

Since play services aren't global on GOS, this patch automatically installs them into the work profile

Whether an app requires play services is automatically detected

Because this needs to happen before the DPC app is triggered in any way in the work profile, this needs to be part of the profile creation itself.

@mkg20001
Copy link
Author

mkg20001 commented Mar 21, 2025

New, simpler approach. No custom permissions, no custom apis

In InstallStart when installing apps it checks if play store is genuine google play store and the user is a work profile and skips the DISALLOW_UNKNOWN_SOURCES restriction

DevicePolicyGmsHooks runs after device policy manager creates the profile and installs store + services and gives the store permission to install packages (REQUEST_INSTALL_PACKAGES) (only if the managing app requires play services)

@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch 2 times, most recently from 65c24ec to 6090d44 Compare March 22, 2025 00:13
@mkg20001
Copy link
Author

mkg20001 commented Mar 24, 2025

I remember last time I was told the play store installation shouldn't happen in DevicePolicyManagerService as it has too many permissions

I need the installation to happen just before the device policy app is installed and gets any intent, as it may crash due to lack of play services.

I'm none the wiser on how to do that securely and I'd appreciate some guidence if possible

@xxxsskxxx
Copy link

Absolute legend mate, thank you so much for continuing to develop and push this!

@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from 6090d44 to b7c9a88 Compare April 5, 2025 23:10
@thestinger thestinger force-pushed the 15-qpr2 branch 5 times, most recently from 5f3142f to 8edf282 Compare April 10, 2025 20:49
@thestinger thestinger force-pushed the 15-qpr2 branch 10 times, most recently from 3ec1472 to ccaf1e6 Compare April 28, 2025 03:31
@loligans
Copy link

loligans commented May 2, 2025

New, simpler approach. No custom permissions, no custom apis

In InstallStart when installing apps it checks if play store is genuine google play store and the user is a work profile and skips the DISALLOW_UNKNOWN_SOURCES restriction

DevicePolicyGmsHooks runs after device policy manager creates the profile and installs store + services and gives the store permission to install packages (REQUEST_INSTALL_PACKAGES) (only if the managing app requires play services)

How do we know the managing app requires play services? For example, Microsoft Company Portal requires it to set up the work profile. Will this change support that use case?

@mkg20001
Copy link
Author

mkg20001 commented May 2, 2025

New, simpler approach. No custom permissions, no custom apis
In InstallStart when installing apps it checks if play store is genuine google play store and the user is a work profile and skips the DISALLOW_UNKNOWN_SOURCES restriction
DevicePolicyGmsHooks runs after device policy manager creates the profile and installs store + services and gives the store permission to install packages (REQUEST_INSTALL_PACKAGES) (only if the managing app requires play services)

How do we know the managing app requires play services? For example, Microsoft Company Portal requires it to set up the work profile. Will this change support that use case?

See 437b272#diff-d0c4fee5a9bb21d19df9696c4428b8053d7842e0e3fde3356fd4bdc335666548R33

@thestinger thestinger force-pushed the 15-qpr2 branch 3 times, most recently from 44f6627 to c0c2721 Compare May 6, 2025 22:55
@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from b7c9a88 to bdfe2c2 Compare May 14, 2025 14:19
@thestinger thestinger force-pushed the 15-qpr2 branch 2 times, most recently from 1e77b17 to acd9811 Compare May 17, 2025 00:40
@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from bdfe2c2 to 006d02d Compare June 13, 2025 09:56
@mkg20001 mkg20001 changed the base branch from 15-qpr2 to 16 June 13, 2025 09:57
@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from 006d02d to b45559b Compare June 14, 2025 13:46
@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from b45559b to 4778e63 Compare June 27, 2025 12:24
@mkg20001
Copy link
Author

Stopped working on android 16, need to find a fix

06-28 01:12:31.831  1339  1888 D ConnectivityService: NetReassign [no changes] [c 1] [a 0] [i 1]
06-28 01:12:31.843   838 11158 I resolv  : GetAddrInfoHandler::run: {101 262245 101 327781 10008 0}
06-28 01:12:31.843   838 11159 I resolv  : res_nmkquery: (QUERY, IN, AAAA)
06-28 01:12:31.843   838 11159 I resolv  : resolv_cache_lookup: FOUND IN CACHE entry=0xb400d0216dc8ae00
06-28 01:12:31.843   838 11159 I resolv  : doQuery: rcode=0, ancount=1, return value=118
06-28 01:12:31.844   838 11160 I resolv  : res_nmkquery: (QUERY, IN, A)
06-28 01:12:31.844   838 11160 I resolv  : resolv_cache_lookup: FOUND IN CACHE entry=0xb400d03f2d464000
06-28 01:12:31.844   838 11160 I resolv  : doQuery: rcode=0, ancount=11, return value=228
06-28 01:12:31.848  6295  6314 I Auth    : [BroadcastManager] [BroadcastManager] Broadcasting bad device management=DeviceManagementRequired [CONTEXT service_id=343 ]
06-28 01:12:31.848  6295  6314 W Auth    : [BroadcastManager] [BroadcastManager] No device or profile owner found for bad device management broadcast. [CONTEXT service_id=343 ]
06-28 01:12:31.849  6295  6314 I Auth    : [AccountStatusChecker]  Canceling DM notification because of DM suppression [CONTEXT service_id=343 ]
06-28 01:12:31.850  6295  6314 W Auth    : [GetToken] GetToken failed with status code: DeviceManagementRequired  [CONTEXT service_id=343 ]
06-28 01:12:31.854  6295  6314 W GLSActivity: [GmsAccountAuthenticatorImpl] error status while fetching token:DeviceManagementRequired
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials: Error refreshing OAuth token
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials: java.io.IOException: Error creating OAuth access token for gRPC calls
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwx$a.a(PG:39)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at tsb.call(PG:139)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.util.concurrent.FutureTask.run(FutureTask.java:317)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwx.a(PG:36)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at nig$b.d(PG:178)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at nig$c.a(PG:49)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwr.a(PG:46)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at nbs.a(PG:47)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xuy$c.a(PG:35)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xun.a(PG:28)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xuv.run(PG:7)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xxw.run(PG:12)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:651)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.lang.Thread.run(Thread.java:1119)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials: Caused by: hpz
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at got.e(PG:275)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hpt.b(PG:20)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwx$a.a(PG:21)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   ... 14 more
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials: Error refreshing OAuth token
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials: java.io.IOException: Error creating OAuth access token for gRPC calls
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwx$a.a(PG:39)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at tsb.call(PG:139)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.util.concurrent.FutureTask.run(FutureTask.java:317)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwx.a(PG:36)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at nig$b.d(PG:178)

06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at nig$c.a(PG:49)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwr.a(PG:46)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at nbs.a(PG:47)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xuy$c.a(PG:35)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xun.a(PG:28)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xuv.run(PG:7)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at xxw.run(PG:12)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:651)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at java.lang.Thread.run(Thread.java:1119)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials: Caused by: hpz
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at got.e(PG:275)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hpt.b(PG:20)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   at hwx$a.a(PG:21)
06-28 01:12:31.859 10485 11107 E OAuth2CallCredentials:   ... 14 more
06-28 01:12:31.860 10485 11107 W AuthRetryClientIntercep: Failed to re-auth on retry.
06-28 01:12:31.860 10485 11107 W AuthRetryClientIntercep: Failed to re-auth on retry.
06-28 01:12:31.861 10485 10586 E GoogleOneUtils: PromoApi caused exception: xsd: UNAUTHENTICATED
06-28 01:12:31.861 10485 10586 E GoogleOneUtils: PromoApi caused exception: xsd: UNAUTHENTICATED

@mkg20001
Copy link
Author

mkg20001 commented Jul 1, 2025

new issue, play store is not being copied.

@cameronaaron
Copy link

This would fix a lot of issues lol

@xxxsskxxx
Copy link

Hi just checking, are there plans to merge this yet? Thanks

@mkg20001
Copy link
Author

This is currently broken and i have no resources to update and fix

@cyberpunked1985
Copy link

This is currently broken and i have no resources to update and fix

What?! Please noo. :'(

@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from 0742a64 to 19dcbdc Compare November 28, 2025 19:08
@thestinger thestinger changed the base branch from 16 to 16-qpr1 November 28, 2025 20:49
@mkg20001
Copy link
Author

mkg20001 commented Nov 29, 2025

@muhomorr I don't have the skill to comply with your requirements and I'm not sure I have the mind for fixing this up. You could look into this, all it essentially does is copy the play store / framework with installExisting and add a special exception to the policy of unknown sources when the work profile app has a play services dependency

@AtlasPilotPuppy
Copy link

This is currently broken and i have no resources to update and fix

I am happy to help if you catch me up a little bit. This would solve the only reason i still have a stock android device - for a work profile

When setting up a google-managed work profile, GmsCore tries to install the Android Device Policy app

For this to work REQUEST_INSTALL_PACKAGES permission needs to be in it's manifest
…nto work profile

Currently when creating a work profile with a DPC app that requires play
services,
the DPC app expects play services to also exist on the work profile

Since play services aren't global on GOS, this patch automatically
installs them
into the work profile

Whether an app requires play services is automatically detected

Because this needs to happen before the DPC app is triggered in any way
in the work
profile, this needs to be part of the profile creation itself.
When a work profile with play services gets created Play Store can't 
install any apps
as the work profile may have a policy active to forbid unknown sources 
as it is not
aware that play store is not a system app and gets blocked by that 
policy.

Here we detect if the play store is genuine and is trying to install an 
app
in a work profile. If that is the case we allow it to proceed, despite 
not being a
@mkg20001 mkg20001 force-pushed the gapps-work-profile-new branch from 19dcbdc to 4279d22 Compare December 6, 2025 13:38
@mkg20001 mkg20001 changed the base branch from 16-qpr1 to 16-qpr2 December 6, 2025 13:40
@mkg20001
Copy link
Author

mkg20001 commented Dec 6, 2025

I am happy to help if you catch me up a little bit. This would solve the only reason i still have a stock android device - for a work profile

The issue is essentially I'm cloning an instance of something by passing it as a parameter which should not be cloned here https://github.com/GrapheneOS/platform_frameworks_base/pull/147/files#diff-d46ea51799b3e1771bedb5697d2aecdbac71731196b92aafb056154cda6b3927R22120

The other issue is that there are review comments on the old PR about security and how this should be improved that I just don't have the time/energy to look into as android development isn't so big that there would be exact solutions to the comments. You can view the old PR here: GrapheneOS-Archive/platform_frameworks_base-old#559

tl;dr security wise we should not touch devicepolicymanagerservice directly as this service has way too much access, meaning bugs can be catastrophic

@mkg20001
Copy link
Author

mkg20001 commented Dec 6, 2025

@AtlasPilotPuppy as for how it works

  • detect if the app that is managing work profile is using play services (manifest metadata tells us that)
  • if so, check if the genuine play store is installed and use installExisting to copy it over to work profile

also there's an exception in installstart so genuine play store can always install packages in work profiles with unknown sources disabled

@mkg20001
Copy link
Author

mkg20001 commented Dec 6, 2025

Feel free to make a new pr. I can give you access to a work profile account if you need one for testing

Edit: you can msg me at https://t.me/mkg20001

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.

6 participants