From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: flawedworld <flawedworld@flawed.world>
Date: Wed, 1 Sep 2021 20:36:10 +0000
Subject: [PATCH] UserManager app installation restrictions

---
 res/values/strings.xml                        |  2 +
 res/xml/user_details_settings.xml             |  4 ++
 .../settings/users/UserDetailsSettings.java   | 43 ++++++++++++++++---
 3 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/res/values/strings.xml b/res/values/strings.xml
index d7f32ee319..d723977899 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7088,6 +7088,8 @@
     <string name="user_enable_calling">Turn on phone calls</string>
     <!-- Title of preference to enable calling and SMS [CHAR LIMIT=45] -->
     <string name="user_enable_calling_sms">Turn on phone calls &amp; SMS</string>
+    <!-- Title of preference to disallow installing apps [CHAR LIMIT=45] -->
+    <string name="user_disallow_install_apps">Disallow installing apps</string>
     <!-- Title of preference to remove the user [CHAR LIMIT=35] -->
     <string name="user_remove_user">Delete user</string>
     <!-- Title for confirmation of turning on calls [CHAR LIMIT=40] -->
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index 9280ff1163..d0a055fae2 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -29,6 +29,10 @@
             android:key="app_and_content_access"
             android:icon="@drawable/ic_lock_closed"
             android:title="@string/user_restrictions_title" />
+    <SwitchPreference
+            android:icon="@drawable/ic_settings_install"
+            android:key="disallow_install_apps"
+            android:title="@string/user_disallow_install_apps" />
     <com.android.settingslib.RestrictedPreference
             android:key="remove_user"
             android:icon="@drawable/ic_delete"
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 897b3c7b83..dc5dfb1dcc 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -59,6 +59,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
     private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
     private static final String KEY_REMOVE_USER = "remove_user";
     private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
+    private static final String KEY_DISALLOW_INSTALL_APPS = "disallow_install_apps";
 
     /** Integer extra containing the userId to manage */
     static final String EXTRA_USER_ID = "user_id";
@@ -78,6 +79,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
     Preference mAppAndContentAccessPref;
     @VisibleForTesting
     Preference mRemoveUserPref;
+    private SwitchPreference mInstallAppsPref;
 
     @VisibleForTesting
     UserInfo mUserInfo;
@@ -131,12 +133,37 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        if (Boolean.TRUE.equals(newValue)) {
-            showDialog(mUserInfo.isGuest() ? DIALOG_CONFIRM_ENABLE_CALLING
-                    : DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
-            return false;
+        if (preference == mPhonePref) {
+            if (Boolean.TRUE.equals(newValue)) {
+                showDialog(mUserInfo.isGuest() ? DIALOG_CONFIRM_ENABLE_CALLING
+                        : DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
+                return false;
+            }
+            enableCallsAndSms(false);
+        } else if (preference == mInstallAppsPref) {
+            if (mUserInfo.isGuest()) {
+                mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, (Boolean) newValue);
+                mUserManager.setDefaultGuestRestrictions(mDefaultGuestRestrictions);
+
+                // Update the guest's restrictions, if there is a guest
+                // TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
+                // on any existing guest rather than do it here with multiple Binder calls.
+                List<UserInfo> users = mUserManager.getUsers(true);
+                for (UserInfo user: users) {
+                    if (user.isGuest()) {
+                        UserHandle userHandle = UserHandle.of(user.id);
+                        for (String key : mDefaultGuestRestrictions.keySet()) {
+                            mUserManager.setUserRestriction(
+                                    key, mDefaultGuestRestrictions.getBoolean(key), userHandle);
+                        }
+                    }
+                }
+            } else {
+                UserHandle userHandle = UserHandle.of(mUserInfo.id);
+                mUserManager.setUserRestriction(UserManager.DISALLOW_INSTALL_APPS, (Boolean) newValue,
+                        userHandle);
+            }
         }
-        enableCallsAndSms(false);
         return true;
     }
 
@@ -203,6 +230,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
         mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
         mRemoveUserPref = findPreference(KEY_REMOVE_USER);
         mAppAndContentAccessPref = findPreference(KEY_APP_AND_CONTENT_ACCESS);
+        mInstallAppsPref = findPreference(KEY_DISALLOW_INSTALL_APPS);
 
         mSwitchUserPref.setTitle(
                 context.getString(com.android.settingslib.R.string.user_switch_to_user,
@@ -220,6 +248,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
             removePreference(KEY_ENABLE_TELEPHONY);
             removePreference(KEY_REMOVE_USER);
             removePreference(KEY_APP_AND_CONTENT_ACCESS);
+            removePreference(KEY_DISALLOW_INSTALL_APPS);
         } else {
             if (!Utils.isVoiceCapable(context)) { // no telephony
                 removePreference(KEY_ENABLE_TELEPHONY);
@@ -244,10 +273,13 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
                 mPhonePref.setChecked(
                         !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
                 mRemoveUserPref.setTitle(R.string.user_exit_guest_title);
+                removePreference(KEY_DISALLOW_INSTALL_APPS);
             } else {
                 mPhonePref.setChecked(!mUserManager.hasUserRestriction(
                         UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
                 mRemoveUserPref.setTitle(R.string.user_remove_user);
+                mInstallAppsPref.setChecked(mUserManager.hasUserRestriction(
+                        UserManager.DISALLOW_INSTALL_APPS, new UserHandle(userId)));
             }
             if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
                     UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
@@ -257,6 +289,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
             mRemoveUserPref.setOnPreferenceClickListener(this);
             mPhonePref.setOnPreferenceChangeListener(this);
             mAppAndContentAccessPref.setOnPreferenceClickListener(this);
+            mInstallAppsPref.setOnPreferenceChangeListener(this);
         }
     }
 
