seedvault icon indicating copy to clipboard operation
seedvault copied to clipboard

Backup work profile (Shelter)

Open ypid opened this issue 4 years ago • 24 comments

Hi,

I have setup a Android work profile so when I open System -> Backup, the settings app asks in which profile the Seedvault should be opened. Personal profile works as intended. But when I select "Work", it says "Disabled by admin". I am the admin and I did not disable it :) I did a quick grep over frameworks/base, Internet search and logcat. No obvious setting. Do you see a trick to patch Android so that backing up the work profile works?

Keep up the good work!

ypid avatar Mar 09 '20 17:03 ypid

Hey!

I'm thinking this is what you may be looking for: https://github.com/aosp-mirror/platform_packages_apps_settings/blob/master/src/com/android/settings/backup/BackupSettingsHelper.java#L216

Untested, but looks right to me. Let me know if changing that works for you. If it's not there, I would guess it's somewhere around there.

stevesoltys avatar Mar 10 '20 00:03 stevesoltys

Looks promising. I will patch this function to always return true and enable logging in my next build for the 2020-04-05 security patch. For reference, logcat shows getIntentForBackupSettings() of that file is being called when I try to open Seedvault for the work profile:

$ adb logcat -v year,uid,color -s BackupSettingsHelper
--------- beginning of system
--------- beginning of crash
--------- beginning of main
2020-03-13 22:15:18.781 1101000  7049  7049 E BackupSettingsHelper: Backup transport has not provided an intent or the component for the intent is not found!

I will report back.

ypid avatar Mar 13 '20 21:03 ypid

Will close this for now, if you find a good solution I can add it to the documentation so those interested can consider applying the patch.

Thanks for bringing this to our attention.

stevesoltys avatar Mar 27 '20 18:03 stevesoltys

The patch:

project packages/apps/Settings/
diff --git a/packages/apps/Settings/src/com/android/settings/backup/BackupSettingsHelper.java b/packages/apps/Settings/src/com/android/     settings/backup/BackupSettingsHelper.java
index 1d3455b149..52b0d143a0 100644
--- a/packages/apps/Settings/src/com/android/settings/backup/BackupSettingsHelper.java
+++ b/packages/apps/Settings/src/com/android/settings/backup/BackupSettingsHelper.java
@@ -211,15 +211,8 @@ public class BackupSettingsHelper {

     /** Checks if backup service is enabled for this user. */
     public boolean isBackupServiceActive() {
-        boolean backupOkay;
-        try {
-            backupOkay = mBackupManager.isBackupServiceActive(UserHandle.myUserId());
-        } catch (Exception e) {
-            // things go wrong talking to the backup system => ignore and
-            // pass the default 'false' as the "backup is a thing?" state.
-            backupOkay = false;
-        }
-        return backupOkay;
+        Log.d(TAG, "return true without condition checking in isBackupServiceActive");
+        return true;
     }   

     @VisibleForTesting

Does not fully work unfortunately. I don’t get "Disabled by admin" anymore, but a blank screen with only the title "Backup". As if Seedvault was not installed. But I checked, it is installed for the work profile. Note that the blank screen is the same behavior of AOSP without Google stuff when no Seedvault is integrated into the built. So it seems Android does not quite get that Seedvault should also be responsible for the work profile.

From the debug log, we see that isBackupServiceActive() was called three times.

2020-04-12 15:55:45.239  1000 11285 11285 W InputEventReceiver: Attempted to finish an input event but the input event receiver has already 
been disposed.                                                                                                                              
2020-04-12 15:55:45.243 1101000 11656 11656 W ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@b0cce9   
2020-04-12 15:55:45.251 1101000 11656 11656 E BackupSettingsHelper: Backup transport has not provided an intent or the component for the in$ent is not found!
2020-04-12 15:55:45.252  1000  1366 11521 I ActivityTaskManager: START u11 {cmp=com.android.settings/.Settings$PrivacySettingsActivity} fro$ uid 1101000                                                                                                                                
2020-04-12 15:55:45.254  root   832   832 D [email protected]: LAUNCH: 1
2020-04-12 15:55:45.268 1101000 11656 11656 W ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@65c56d2  
2020-04-12 15:55:45.275 1101000 11656 11656 D SettingsActivity: Starting onCreate
2020-04-12 15:55:45.281 1101000 11656 11656 D SettingsActivity: Starting to set activity title            
2020-04-12 15:55:45.281 1101000 11656 11656 D SettingsActivity: Done setting title                                                          
2020-04-12 15:55:45.281 1101000 11656 11656 D SettingsActivity: Switching to fragment com.android.settings.backup.PrivacySettings
2020-04-12 15:55:45.282 1101000 11656 11656 D PrefCtrlListHelper: Could not find Context-only controller for pref: com.android.settings.bac$up.BackupDataPreferenceController
2020-04-12 15:55:45.283 1101000 11656 11656 D PrefCtrlListHelper: Could not find Context-only controller for pref: com.android.settings.bac$up.ConfigureAccountPreferenceController                                                                                                     
2020-04-12 15:55:45.283 1101000 11656 11656 D PrefCtrlListHelper: Could not find Context-only controller for pref: com.android.settings.bac$up.DataManagementPreferenceController                                                                                                       
2020-04-12 15:55:45.283 1101000 11656 11656 D PrefCtrlListHelper: Could not find Context-only controller for pref: com.android.settings.bac$up.AutoRestorePreferenceController                                                                     
2020-04-12 15:55:45.283 1101000 11656 11656 D PrefCtrlListHelper: Could not find Context-only controller for pref: com.android.settings.bac$up.BackupInactivePreferenceController
2020-04-12 15:55:45.285 1101000 11656 11656 D BackupSettingsHelper: return true without condition checking in isBackupServiceActive
2020-04-12 15:55:45.287 1101000 11656 11656 D BackupSettingsHelper: return true without condition checking in isBackupServiceActive         
2020-04-12 15:55:45.289 1101000 11656 11656 D PrivacySettings: NO dashboard tiles for PrivacySettings
2020-04-12 15:55:45.289 1101000 11656 11656 D PrivacySettings: All preferences added, reporting fully drawn                              
2020-04-12 15:55:45.290  1000  1366  1463 I ActivityTaskManager: Fully drawn com.android.settings/.Settings$PrivacySettingsActivity: +62ms  
2020-04-12 15:55:45.290 1101000 11656 11656 D SettingsActivity: Executed frag manager pendingTransactions
2020-04-12 15:55:45.301 1101000 11656 11656 D BackupSettingsHelper: return true without condition checking in isBackupServiceActive         
2020-04-12 15:55:45.302 1101000 11656 11683 W TileUtils: Found com.android.settings.Settings$DataUsageSummaryActivity for intent Intent { a$t=com.android.settings.action.SETTINGS pkg=com.android.settings } missing metadata com.android.settings.category
2020-04-12 15:55:45.309 1101000 11656 11972 D SettingsActivity: No enabled state changed, skipping updateCategory call                    
2020-04-12 15:55:45.331  1000  1366  1463 E system_server: Dex checksum does not match for dex: /product/priv-app/Settings/Settings.apk.Exp$cted: 2833457125, actual: 1132749477

ypid avatar Apr 12 '20 14:04 ypid

I'll re-open this in case anyone else is having this issue and wants to contribute.

It sounds to me like the backup transport is not set for that user. However, I'm not sure if the backup transport setting is per user. There could be other code affecting the backup transport settings for non-admin profiles somewhere else as well.

stevesoltys avatar Apr 13 '20 03:04 stevesoltys

I don’t get "Disabled by admin" anymore, but a blank screen with only the title "Backup". As if Seedvault was not installed.

You might need to set the backup transport for the current user. This sounds like it is set to LocalTransport.

grote avatar Sep 21 '20 13:09 grote

Check the adb shell bmgr --user option.

@chirayudesai is there maybe a way to set the transport automatically for all users, so they don't end up in that empty activity?

grote avatar Sep 21 '20 13:09 grote

@grote probably, need to check.

Will it work with other users though? We should test that before we enable it.

chirayudesai avatar Sep 21 '20 14:09 chirayudesai

It should work™, but yeah we should do our own tests before enabling this in production. If it works, that's probably something for an OEM documentation.

grote avatar Sep 21 '20 14:09 grote

Oh you know, this could also be useful for testing on the same device. I can add the restore activity to the per-user setupwizard.

Then you can just create a new user, and then restore a backup made on the main/other user.

chirayudesai avatar Sep 22 '20 12:09 chirayudesai

What I've tried:

  • Turn on multiple users in Settings -> System -> Advanced -> Multiple users
  • Add new user
  • Switch to new user, including Set up now
  • Settings -> System -> Backup is Not available
  • Get current user ID with adb shell am get-current-user
  • adb shell bmgr --user [ID] list transports returns Error: Backup Manager is not activated for user [ID]
  • to activate adb shell bmgr --user [ID] activate true (no OS patch needed)
  • Settings -> System -> Backup is now empty like for op
  • adb shell bmgr --user [ID] list transports now returns our transport
  • adb shell bmgr --user [ID] transport com.stevesoltys.seedvault.transport.ConfigurableBackupTransport to activate it
  • try a backup and see things working on a first glance

There even seems to be a different view on internal storage, so if you back up to that, the files don't conflict between users.

@ypid can you confirm that this work for you? Please let us know if there's other issues with Seedvault in different user-profiles!

grote avatar Sep 22 '20 14:09 grote

I now also tried the Shelter app (which is pretty sweet btw.). There am get-current-user doesn't help you. You need adb shell pm list users which really lists all users. You'll find your work profile there and then can do bmgr activate true like above.

@chirayudesai the activate and transport set steps ideally are something that we can automatically to on a ROM level for all current and future users maybe?

grote avatar Sep 22 '20 14:09 grote

@chirayudesai the activate and transport set steps ideally are something that we can automatically to on a ROM level for all current and future users maybe?

Yes now that you've confirmed it works we should do that. Did you try restoring?

I think we could do it for 11, and just document the steps you did for 10 if that's fine.

chirayudesai avatar Sep 22 '20 15:09 chirayudesai

A full restore works, but I couldn't get Auto-Restore to work. There's not really any clues in the log, just that the system tries all(?) users for a backup agent of the package I am restoring, but then doing nothing. This might be unrelated as I couldn't get it to work in the personal/main profile.

grote avatar Sep 22 '20 17:09 grote

So that's strange: Auto-Restore for the owner profile only started to work again after I deleted the users manually with pm remove-user (Shelter doesn't seem to have an option to remove the work profile again). Then after adding one user and installing the same app there, it still worked. App auto restore for the user did not work tough and afterwards also stopped working for the owner.

Might be an AOSP bug since backup multi-user support was only introduced in Android 10 with a few commits and not touched since. Also, this is all system APIs, Seedvault isn't even called at that point.

grote avatar Sep 22 '20 17:09 grote

@ypid can you confirm that this work for you? Please let us know if there's other issues with Seedvault in different user-profiles!

@grote With your help, I managed to enable Seedvault for a new user. But not for my work profile. Testing was done on AOSP 10.

$ adb shell pm list users
Users:
        UserInfo{0:Owner:13} running
        UserInfo{10:New user:10} running
        UserInfo{11:Work profile:30} running
$ adb shell bmgr --user 0 list transports

    com.android.localtransport/.LocalTransport
  * com.stevesoltys.seedvault.transport.ConfigurableBackupTransport
$ for i in 10 11; do adb shell bmgr --user $i enabled; done
Error: Could not access the Backup Manager.  Is the system running?
Error: Could not access the Backup Manager.  Is the system running?
$ for i in 10 11; do adb shell bmgr --user $i actived; done
Error: Could not access the Backup Manager.  Is the system running?
Error: Could not access the Backup Manager.  Is the system running?
$ for i in 10 11; do adb shell bmgr --user $i enable true; done
Error: Could not access the Backup Manager.  Is the system running?
Error: Could not access the Backup Manager.  Is the system running?
$ for i in 10 11; do adb shell bmgr --user $i activate true; done
Backup service now activated for user 10
Exception caught:
java.lang.SecurityException: No permission to configure backup activity
        at android.os.Parcel.createException(Parcel.java:2071)
        at android.os.Parcel.readException(Parcel.java:2039)
        at android.os.Parcel.readException(Parcel.java:1987)
        at android.app.backup.IBackupManager$Stub$Proxy.setBackupServiceActive(IBackupManager.java:3317)
        at com.android.commands.bmgr.Bmgr.doActivateService(Bmgr.java:882)
        at com.android.commands.bmgr.Bmgr.run(Bmgr.java:111)
        at com.android.commands.bmgr.Bmgr.main(Bmgr.java:86)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:338)
Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.server.backup.Trampoline.enforcePermissionsOnUser(Trampoline.java:309)
        at com.android.server.backup.Trampoline.setBackupServiceActive(Trampoline.java:326)
        at android.app.backup.IBackupManager$Stub.onTransact(IBackupManager.java:1667)
        at android.os.Binder.execTransactInternal(Binder.java:1021)
        at android.os.Binder.execTransact(Binder.java:994)

$ adb shell bmgr --user 10 list transports
    com.android.localtransport/.LocalTransport
  * com.stevesoltys.seedvault.transport.ConfigurableBackupTranspor

I could imaging that the issue I cannot activate the Backup service for my work profile is because I installed Seedvault after setting up the work profile. I will test this when I will start working on Android 11.

ypid avatar Sep 22 '20 21:09 ypid

Error: Could not access the Backup Manager. Is the system running? sounds strange, I've never seen this. Might be worth checking the logs for something related.

The No permission to configure backup activity seems to throw here: http://aosp.opersys.com/xref/android-10.0.0_r46/xref/frameworks/base/services/backup/java/com/android/server/backup/Trampoline.java#313

I tested this on a userdebug build and might have done adb root before.

grote avatar Sep 23 '20 11:09 grote

I have the exact same No permission to configure backup activity:

~/M/o/Pixel3a> adb shell pm list users
Users:
        UserInfo{0:Owner:13} running
        UserInfo{10:Work profile:30} running
~/M/o/Pixel3a> adb shell bmgr --user 10 activate true
Exception caught:
java.lang.SecurityException: No permission to configure backup activity

Pixel3a running CalyxOS. Is there any info I can collect to troubleshoot?

tve avatar Sep 25 '20 08:09 tve

Checking the logs makes sense of course :)

I disabled the second user again:

adb shell pm list users                
Users:
        UserInfo{0:Owner:13} running
        UserInfo{11:Work profile:30} running

adb shell bmgr --user 10 enable true

# Output: Error: Could not access the Backup Manager.  Is the system running?
2020-09-25 09:56:35.320 shell 20527 20527 D AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<               
2020-09-25 09:56:35.356 shell 20527 20527 W app_process: type=1400 audit(0.0:15256): avc: denied { read } for name="u:object_r:device_config_runtime_native_boot_prop:s0" dev="tmpfs" ino=21722 scontext=u:r:shell:s0 tcontext=u:object_r:device_config_runtime_native_boot_prop:s0 tclass=file permissive=0
2020-09-25 09:56:35.360 shell 20527 20527 E libc    : Access denied finding property "persist.device_config.runtime_native_boot.enable_apex_image"
2020-09-25 09:56:35.360 shell 20527 20527 I AndroidRuntime: Using default boot image                                                       
2020-09-25 09:56:35.361 shell 20527 20527 E libc    : Access denied finding property "persist.device_config.runtime_native_boot.disable_lock_profiling"
2020-09-25 09:56:35.361 shell 20527 20527 I AndroidRuntime: Leaving lock profiling enabled                                                 
2020-09-25 09:56:35.361 shell 20527 20527 E libc    : Access denied finding property "persist.device_config.runtime_native_boot.enable_generational_cc"
2020-09-25 09:56:35.356 shell 20527 20527 W app_process: type=1400 audit(0.0:15257): avc: denied { read } for name="u:object_r:device_config_runtime_native_boot_prop:s0" dev="tmpfs" ino=21722 scontext=u:r:shell:s0 tcontext=u:object_r:device_config_runtime_native_boot_prop:s0 tclass=file permissive=0
2020-09-25 09:56:35.815 shell 20527 20527 D ICU     : Time zone APEX file found: /apex/com.android.tzdata/etc/icu/icu_tzdata.dat
2020-09-25 09:56:35.892 shell 20527 20527 I app_process: The ClassLoaderContext is a special shared library.
2020-09-25 09:56:35.933 shell 20527 20527 W app_process: JNI RegisterNativeMethods: attempt to register 0 native methods for android.media.AudioAttributes
2020-09-25 09:56:35.950 shell 20527 20527 D AndroidRuntime: Calling main entry com.android.commands.bmgr.Bmgr
2020-09-25 09:56:35.953 shell 20527 20527 V Bmgr    : Running enable for user:10
2020-09-25 09:56:35.957 shell 20527 20527 D AndroidRuntime: Shutting down VM
  • E libc : Access denied finding property "persist.device_config.runtime_native_boot.enable_apex_image" You find some error reports online where this log line is also part of for example https://github.com/GrapheneOS/os_issue_tracker/issues/147 So I stop my research about this log line for now.

  • W app_process: type=1400 audit(0.0:15267): avc: denied { read } for name="u:object_r:device_config_runtime_native_boot_prop:s0" dev="tmpfs" ino=21722 scontext=u:r:shell:s0 tcontext=u:object_r:device_config_runtime_native_boot_prop:s0 tclass=file permissive=0

    Looks to me like a SELinux deny. I have no deep knowledge of SELinux yet unfortunate and cannot find any results for this exact warning.

  • W app_process: JNI RegisterNativeMethods: attempt to register 0 native methods for android.media.AudioAttributes Some media audio warning which I can probably ignore. For reference, I found reports including this line about something not working when the screen was off (which is the case). So I unlocked and put an work space app in the foreground. Does not change.

adb shell bmgr --user 10 activate true

Output: Exception caught:
Output: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.pm.UserInfo.isManagedProfile()' on a null object reference

[Logcat output is very similar. I diffed it.

 D AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
+W app_process: type=1400 audit(0.0:15256): avc: denied { read } for name="u:object_r:device_config_runtime_native_boot_prop:s0" dev="tmpfs" ino=21722 scontext=u:r:shell:s0 tcontext=u:object_r:device_config_runtime_native_boot_prop:s0 tclass=file permissive=0
 E libc    : Access denied finding property "persist.device_config.runtime_native_boot.enable_apex_image"
 I AndroidRuntime: Using default boot image
 E libc    : Access denied finding property "persist.device_config.runtime_native_boot.disable_lock_profiling"
 I AndroidRuntime: Leaving lock profiling enabled
 E libc    : Access denied finding property "persist.device_config.runtime_native_boot.enable_generational_cc"
-W app_process: type=1400 audit(0.0:15267): avc: denied { read } for name="u:object_r:device_config_runtime_native_boot_prop:s0" dev="tmpfs" ino=21722 scontext=u:r:shell:s0 tcontext=u:object_r:device_config_runtime_native_boot_prop:s0 tclass=file permissive=0
+W app_process: type=1400 audit(0.0:15257): avc: denied { read } for name="u:object_r:device_config_runtime_native_boot_prop:s0" dev="tmpfs" ino=21722 scontext=u:r:shell:s0 tcontext=u:object_r:device_config_runtime_native_boot_prop:s0 tclass=file permissive=0
 D ICU     : Time zone APEX file found: /apex/com.android.tzdata/etc/icu/icu_tzdata.dat
 I app_process: The ClassLoaderContext is a special shared library.
 W app_process: JNI RegisterNativeMethods: attempt to register 0 native methods for android.media.AudioAttributes
 D AndroidRuntime: Calling main entry com.android.commands.bmgr.Bmgr
-V Bmgr    : Running activate for user:10
+V Bmgr    : Running enable for user:10
 D AndroidRuntime: Shutting down VM

I am still running on the same exact build and only removed the user, but I now get java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.pm.UserInfo.isManagedProfile()' on a null object reference which is something to work with I guess. Out of interest, I added a second user and still get the exception in android.content.pm.UserInfo.isManagedProfile()'. I have not looked into this function. I might do that in a few weeks.

I tested this on a userdebug build and might have done adb root before.

That is what I had in mind. I will probably test with a userdebug build when I get into Android 11 migration work. So you might have cheated :)

ypid avatar Sep 25 '20 08:09 ypid

Had a chat with the Shelter dev. The problem is probably https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setBackupServiceEnabled(android.content.ComponentName,%20boolean) They should have a new release in the next few days with support for Android 11. Said that after that they are happy to add a setting to allow backups to be enabled.

dznsm avatar Sep 25 '20 08:09 dznsm

Yeah, if Shelter could add an option to enable backups (or just do it unconditionally) that would be best I guess.

@ypid thanks for the logs and research. That sounds like something @chirayudesai might want to look into.

grote avatar Sep 25 '20 11:09 grote

I guess we could close this, right?

grote avatar Nov 19 '20 12:11 grote

Hi, this was the first search result for "backup work profile" in duckduckgo-privacybrowser...does that mean it's currently impossible to back up a work profile, making impossible to try other sandboxing apps (for example, switching from shelter to insular to see if insular supports updating apps that are frozen but aren't cloned), without loosing every app, file, etc, in ones work profile?

neurodiverseEsoteric avatar Apr 01 '21 16:04 neurodiverseEsoteric

https://review.calyxos.org/c/CalyxOS/platform_packages_apps_Settings/+/3478

I successfully backed up a work profile to internal storage using the patch above. Now the question is about restoring it.

Additionally I noticed that backing up to USB was not available on the work profile

Uldiniad avatar May 15 '21 02:05 Uldiniad

closing as per https://github.com/seedvault-app/seedvault/issues/77#issuecomment-730355616

work profile support for seedvault in calyxos has improved a lot since then

grote avatar May 31 '24 20:05 grote