Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse RadioPickerFragment2 for restricting user app install setting + Support to hide system apps for install available apps feature #294

Open
wants to merge 4 commits into
base: 15
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/com/android/settings/users/AppCopyFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ private void populateApps() {
if (app.packageName == null) continue;

final AppSwitchPreference p = new AppSwitchPreference(getPrefContext());
if (AppCopyFragmentHelperExt.maybeSkipOrModifyAppSwitchPref(this, app, p)) {
continue;
}
p.setIcon(app.icon != null ? app.icon.mutate() : null);
p.setChecked(false);
p.setTitle(app.appName);
Expand Down
96 changes: 96 additions & 0 deletions src/com/android/settings/users/AppCopyFragmentHelperExt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.android.settings.users;

import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.settingslib.users.AppCopyHelper;
import com.android.settingslib.widget.AppSwitchPreference;

import java.util.ArrayList;
import java.util.List;

public class AppCopyFragmentHelperExt {

public static final String EXTRA_FOR_PRIVATE_SPACE = "com.android.settings.users.extra.FOR_PRIVATE_SPACE";
public static final String EXTRA_SHOW_USER_APPS_ONLY = "com.android.settings.users.extra.SHOW_USER_APPS_ONLY";

static boolean maybeSkipOrModifyAppSwitchPref(
@NonNull AppCopyFragment appCopyFragment,
@NonNull AppCopyHelper.SelectableAppInfo selectableAppInfo,
@NonNull AppSwitchPreference appSwitchPreference) {
Bundle args = appCopyFragment.getArguments();
if (args == null) {
return false;
}

maybeModifyAppSwitchPref(appCopyFragment, selectableAppInfo, appSwitchPreference);
boolean forPrivateSpace = args.getBoolean(EXTRA_FOR_PRIVATE_SPACE, false);
boolean showUserAppsOnly = args.getBoolean(EXTRA_SHOW_USER_APPS_ONLY, false);
if (!showUserAppsOnly) {
return false;
}

Context ctx = appCopyFragment.requireContext();
PackageManager pm = ctx.getPackageManager();
String pkgName = selectableAppInfo.packageName;
List<String> allowedSystemApps = new ArrayList<>();
if (forPrivateSpace) {
allowedSystemApps.add("com.android.gallery3d");
}

final PackageInfo pi;
try {
PackageManager.PackageInfoFlags flags = PackageManager.PackageInfoFlags.of(
PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.GET_SIGNING_CERTIFICATES
);
pi = pm.getPackageInfo(pkgName, flags);
} catch (PackageManager.NameNotFoundException e) {
return false;
}

if (pi == null) {
return false;
}

final ApplicationInfo ai = pi.applicationInfo;
if (ai == null) {
return false;
}


if (ai.isSystemApp()) {
if (!allowedSystemApps.contains(pkgName)) {
return true;
}
}

return false;
}

private static void maybeModifyAppSwitchPref(
@NonNull AppCopyFragment appCopyFragment,
@NonNull AppCopyHelper.SelectableAppInfo selectableAppInfo,
@NonNull AppSwitchPreference appSwitchPreference) {
}

public static Bundle appendArgs(
@Nullable Bundle bundle, @UserIdInt int userId,
boolean forPrivateSpace, boolean showUserAppsOnly) {
Bundle res = bundle != null ? bundle : new Bundle();
res.putInt(AppCopyFragment.EXTRA_USER_ID, userId);
res.putBoolean(EXTRA_FOR_PRIVATE_SPACE, forPrivateSpace);
res.putBoolean(EXTRA_SHOW_USER_APPS_ONLY, showUserAppsOnly);
return res;
}

private AppCopyFragmentHelperExt() {
}
}
12 changes: 8 additions & 4 deletions src/com/android/settings/users/UserAppsInstallSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;

import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
Expand All @@ -27,6 +28,7 @@

public class UserAppsInstallSettings extends RadioButtonPickerFragment {

private static final String TAG = "UserAppsInstallSettings";
private static final String INSTALL_ENABLED = "install_apps_enabled";
private static final String INSTALL_FIRST_PARTY_ENABLED = "install_apps_first_party_enabled";
private static final String INSTALL_DISABLED = "install_apps_disabled";
Expand Down Expand Up @@ -75,11 +77,13 @@ static String getDescription(Context context, UserRestrictions userRestrictions)
public void onCreate(Bundle savedInstanceState) {
Bundle args = requireArguments();
int userId = args.getInt(EXTRA_USER_ID, UserHandle.USER_NULL);

Context ctx = requireContext();
UserManager userManager = ctx.getSystemService(UserManager.class);
UserInfo userInfo = userManager.getUserInfo(userId);
userRestrictions = new UserRestrictions(userManager, userInfo);
userRestrictions = UserRestrictions.createInstance(ctx, userId);
if (userRestrictions == null) {
Log.w(TAG, "Unable to fetch user info for provided userId");
finishFragment();
return;
}

super.onCreate(savedInstanceState);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.android.settings.users;

import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;

import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.ext.AbstractListPreferenceController;
import com.android.settings.ext.RadioButtonPickerFragment2;
import com.android.settingslib.widget.CandidateInfo;

import java.util.ArrayList;

public class UserAppsInstallSettingsPrefController extends AbstractListPreferenceController {

private static final int UNKNOWN = -1;
private static final int INSTALL_ENABLED = 0;
private static final int INSTALL_FIRST_PARTY_ENABLED = 1;
private static final int INSTALL_DISABLED = 2;

static void launchSettings(Context context, Preference preference, int userId) {
preference.getExtras().putInt(AppCopyFragment.EXTRA_USER_ID, userId);
new UserAppsInstallSettingsPrefController(context, preference.getKey())
.handlePreferenceTreeClick(preference);
}

protected UserRestrictions userRestrictions;

public UserAppsInstallSettingsPrefController(Context ctx, String key) {
super(ctx, key);
}

@Override
public int getAvailabilityStatus() {
if (userRestrictions == null) {
return CONDITIONALLY_UNAVAILABLE;
}

return AVAILABLE;
}

@Override
public void updateState(Preference p) {
super.updateState(p);
}

@Override
protected void getEntries(Entries entries) {
if (fragment == null) {
throw new IllegalStateException();
}
Bundle args = fragment.getArguments();
if (args == null) {
throw new IllegalStateException();
}

int userId = args.getInt(AppCopyFragment.EXTRA_USER_ID, UserHandle.USER_NULL);
userRestrictions = UserRestrictions.createInstance(mContext, userId);
if (userRestrictions == null) {
throw new IllegalStateException();
}

UserInfo userInfo = userRestrictions.userInfo;

if (!userInfo.isGuest()) {
entries.add(R.string.user_app_install_enabled,
R.string.user_app_install_enabled_desc,
INSTALL_ENABLED);
}

entries.add(R.string.user_app_install_enabled_first_party_sources,
R.string.user_app_install_enabled_first_party_sources_desc,
INSTALL_FIRST_PARTY_ENABLED);
entries.add(R.string.user_app_install_disabled,
R.string.user_app_install_disabled_desc,
INSTALL_DISABLED);
}

@Override
protected final int getCurrentValue() {
if (userRestrictions == null) {
return UNKNOWN;
}

final boolean isInstallDisallowed =
userRestrictions.isSet(UserManager.DISALLOW_INSTALL_APPS);
final boolean isInstallDisallowedForUnknownSources =
userRestrictions.isSet(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
if (isInstallDisallowed) {
if (isInstallDisallowedForUnknownSources) {
return INSTALL_DISABLED;
}

return UNKNOWN;
}

if (isInstallDisallowedForUnknownSources) {
return INSTALL_FIRST_PARTY_ENABLED;
}

return INSTALL_ENABLED;
}

@Override
protected final boolean setValue(int installEnabledValue) {
if (userRestrictions == null) {
return false;
}

switch (installEnabledValue) {
case INSTALL_ENABLED -> {
userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false);
userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
return true;
}
case INSTALL_FIRST_PARTY_ENABLED -> {
userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false);
userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
return true;
}
case INSTALL_DISABLED -> {
userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, true);
userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
return true;
}
}

return false;
}
}
4 changes: 2 additions & 2 deletions src/com/android/settings/users/UserDetailsSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public boolean onPreferenceClick(Preference preference) {
openAppCopyingScreen();
return true;
} else if (preference == mAppsInstallsPref) {
UserAppsInstallSettings.launch(preference, mUserInfo.id);
UserAppsInstallSettingsPrefController.launchSettings(requireContext(), preference, mUserInfo.id);
return true;
}
return false;
Expand Down Expand Up @@ -357,7 +357,7 @@ void initialize(Context context, Bundle arguments) {
boolean isNewUser =
arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
mUserInfo = mUserManager.getUserInfo(userId);
userRestrictions = new UserRestrictions(mUserManager, mUserInfo);
userRestrictions = UserRestrictions.createInstance(mUserManager, mUserInfo);

mSwitchUserPref = findPreference(KEY_SWITCH_USER);
mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
Expand Down
44 changes: 36 additions & 8 deletions src/com/android/settings/users/UserRestrictions.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,51 @@
package com.android.settings.users;

import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;

import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

final class UserRestrictions {
public final class UserRestrictions {

final UserManager userManager;
final UserInfo userInfo;
@NonNull
private final UserManager userManager;
@NonNull
public final UserInfo userInfo;

UserRestrictions(UserManager userManager, UserInfo userInfo) {
@Nullable
public static UserRestrictions createInstance(@NonNull Context ctx, int userId) {
UserManager userManager = ctx.getSystemService(UserManager.class);
if (userManager == null) {
return null;
}

return createInstance(userManager, userId);
}

@Nullable
public static UserRestrictions createInstance(@NonNull UserManager userManager, int userId) {
UserInfo userInfo = userManager.getUserInfo(userId);
if (userInfo == null) {
return null;
}

return new UserRestrictions(userManager, userInfo);
}

@NonNull
public static UserRestrictions createInstance(@NonNull UserManager userManager, @NonNull UserInfo userInfo) {
return new UserRestrictions(userManager, userInfo);
}

private UserRestrictions(@NonNull UserManager userManager, @NonNull UserInfo userInfo) {
this.userManager = userManager;
this.userInfo = userInfo;
}

boolean isSet(String restrictionKey) {
public boolean isSet(String restrictionKey) {
final boolean isSetFromUser = userManager.hasUserRestriction(restrictionKey, userInfo.getUserHandle());
if (userInfo.isGuest()) {
return isSetFromUser || userManager.getDefaultGuestRestrictions().getBoolean(restrictionKey);
Expand All @@ -26,7 +54,7 @@ boolean isSet(String restrictionKey) {
return isSetFromUser;
}

void set(String restrictionKey, boolean enableRestriction) {
public void set(String restrictionKey, boolean enableRestriction) {
if (userInfo.isGuest()) {
Bundle defaultGuestRestrictions = userManager.getDefaultGuestRestrictions();
defaultGuestRestrictions.putBoolean(restrictionKey, enableRestriction);
Expand Down