fix: 首次提交

This commit is contained in:
2024-12-09 11:25:23 +08:00
parent d0c01071e9
commit 2c2109a5f3
4741 changed files with 290641 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.DialogInterface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
/**
* A controller used to customize the action disabled by admin dialog.
*/
public interface ActionDisabledByAdminController {
/**
* Sets the {@link ActionDisabledLearnMoreButtonLauncher}.
*/
void initialize(ActionDisabledLearnMoreButtonLauncher launcher);
/**
* Handles the adding and setting up of the learn more button. If button is not needed, then
* this method can be left empty.
*/
void setupLearnMoreButton(Context context);
/**
* Returns the admin support dialog's title resource id.
*/
String getAdminSupportTitle(@Nullable String restriction);
/**
* Returns the admin support dialog's content string.
*/
CharSequence getAdminSupportContentString(Context context,
@Nullable CharSequence supportMessage);
/**
* Updates the enforced admin
*/
void updateEnforcedAdmin(RestrictedLockUtils.EnforcedAdmin admin, @UserIdInt int adminUserId);
/**
* Returns a listener for handling positive button clicks
*/
@Nullable
default DialogInterface.OnClickListener getPositiveButtonListener(@NonNull Context context,
@NonNull RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
return null;
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static com.android.settingslib.enterprise.ActionDisabledLearnMoreButtonLauncher.DEFAULT_RESOLVE_ACTIVITY_CHECKER;
import static com.android.settingslib.enterprise.ManagedDeviceActionDisabledByAdminController.DEFAULT_FOREGROUND_USER_CHECKER;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.ParentalControlsUtilsInternal;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.text.TextUtils;
/**
* A factory that returns the relevant instance of {@link ActionDisabledByAdminController}.
*/
public final class ActionDisabledByAdminControllerFactory {
/**
* Returns the relevant instance of {@link ActionDisabledByAdminController}.
* @param userHandle user on which to launch the help page, if necessary
*/
public static ActionDisabledByAdminController createInstance(Context context,
String restriction, DeviceAdminStringProvider stringProvider,
UserHandle userHandle) {
if (doesBiometricRequireParentalConsent(context, restriction)) {
return new BiometricActionDisabledByAdminController(stringProvider);
} else if (isFinancedDevice(context)) {
return new FinancedDeviceActionDisabledByAdminController(stringProvider);
} else if (isSupervisedDevice(context)) {
return new SupervisedDeviceActionDisabledByAdminController(stringProvider, restriction);
} else {
return new ManagedDeviceActionDisabledByAdminController(
stringProvider,
userHandle,
DEFAULT_FOREGROUND_USER_CHECKER,
DEFAULT_RESOLVE_ACTIVITY_CHECKER);
}
}
private static boolean isSupervisedDevice(Context context) {
DevicePolicyManager devicePolicyManager =
context.getSystemService(DevicePolicyManager.class);
ComponentName supervisionComponent =
devicePolicyManager.getProfileOwnerOrDeviceOwnerSupervisionComponent(
new UserHandle(UserHandle.myUserId()));
return supervisionComponent != null;
}
/**
* @return true if the restriction == UserManager.DISALLOW_BIOMETRIC and parental consent
* is required.
*/
private static boolean doesBiometricRequireParentalConsent(Context context,
String restriction) {
if (!TextUtils.equals(UserManager.DISALLOW_BIOMETRIC, restriction)) {
return false;
}
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
return ParentalControlsUtilsInternal.parentConsentRequired(context, dpm,
BiometricAuthenticator.TYPE_ANY_BIOMETRIC, new UserHandle(UserHandle.myUserId()));
}
private static boolean isFinancedDevice(Context context) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
// TODO(b/259908270): remove
if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
DevicePolicyManager.ADD_ISFINANCED_DEVICE_FLAG,
DevicePolicyManager.ADD_ISFINANCED_FEVICE_DEFAULT)) {
return dpm.isFinancedDevice();
}
return dpm.isDeviceManaged() && dpm.getDeviceOwnerType(
dpm.getDeviceOwnerComponentOnAnyUser()) == DEVICE_OWNER_TYPE_FINANCED;
}
private ActionDisabledByAdminControllerFactory() {
throw new UnsupportedOperationException("provides only static methods");
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import static java.util.Objects.requireNonNull;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
/**
* Helper class meant to set up the "Learn more" button in the action disabled dialog.
*/
public abstract class ActionDisabledLearnMoreButtonLauncher {
public static ResolveActivityChecker DEFAULT_RESOLVE_ACTIVITY_CHECKER =
(packageManager, url, userHandle) -> packageManager.resolveActivityAsUser(
createLearnMoreIntent(url),
PackageManager.MATCH_DEFAULT_ONLY,
userHandle.getIdentifier()) != null;
interface ResolveActivityChecker {
boolean canResolveActivityAsUser(
PackageManager packageManager, String url, UserHandle userHandle);
}
/**
* Sets up a "learn more" button which shows a screen with device policy settings
*/
public final void setupLearnMoreButtonToShowAdminPolicies(Context context,
int enforcementAdminUserId, EnforcedAdmin enforcedAdmin) {
requireNonNull(context, "context cannot be null");
// The "Learn more" button appears only if the restriction is enforced by an admin in the
// same profile group or by the device owner. Otherwise the admin package and its policies
// are not accessible to the current user.
if (isSameProfileGroup(context, enforcementAdminUserId)
|| isEnforcedByDeviceOwnerOnSystemUserMode(context, enforcementAdminUserId)) {
setLearnMoreButton(() -> showAdminPolicies(context, enforcedAdmin));
}
}
/**
* Sets up a "learn more" button which launches a help page
*/
public final void setupLearnMoreButtonToLaunchHelpPage(
Context context, String url, UserHandle userHandle) {
requireNonNull(context, "context cannot be null");
requireNonNull(url, "url cannot be null");
setLearnMoreButton(() -> showHelpPage(context, url, userHandle));
}
/**
* Sets the "learning more" button.
*
* @param action action to be run when the button is tapped.
*/
public abstract void setLearnMoreButton(Runnable action);
/**
* Launches the settings page with info about the given admin.
*/
protected abstract void launchShowAdminPolicies(Context context, UserHandle user,
ComponentName admin);
/**
* Launches the settings page that shows all admins.
*/
protected abstract void launchShowAdminSettings(Context context);
/**
* Callback to finish the activity associated with the launcher.
*/
protected void finishSelf() {
}
@VisibleForTesting
protected boolean isSameProfileGroup(Context context, int enforcementAdminUserId) {
UserManager um = context.getSystemService(UserManager.class);
return um.isSameProfileGroup(enforcementAdminUserId, um.getProcessUserId());
}
private boolean isEnforcedByDeviceOwnerOnSystemUserMode(
Context context, int enforcementAdminUserId) {
if (enforcementAdminUserId != UserHandle.USER_SYSTEM) {
return false;
}
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
return enforcementAdminUserId == dpm.getDeviceOwnerUserId();
}
/**
* Shows the help page using the given {@code url}.
*/
@VisibleForTesting
public void showHelpPage(Context context, String url, UserHandle userHandle) {
context.startActivityAsUser(createLearnMoreIntent(url), userHandle);
finishSelf();
}
protected final boolean canLaunchHelpPage(
PackageManager packageManager,
String url,
UserHandle userHandle,
ResolveActivityChecker resolveActivityChecker) {
return resolveActivityChecker.canResolveActivityAsUser(packageManager, url, userHandle);
}
private void showAdminPolicies(Context context, EnforcedAdmin enforcedAdmin) {
if (enforcedAdmin != null && enforcedAdmin.component != null) {
launchShowAdminPolicies(context, enforcedAdmin.user, enforcedAdmin.component);
} else {
launchShowAdminSettings(context);
}
finishSelf();
}
private static Intent createLearnMoreIntent(String url) {
return new Intent(Intent.ACTION_VIEW, Uri.parse(url)).setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import static java.util.Objects.requireNonNull;
import android.annotation.UserIdInt;
import com.android.internal.util.Preconditions;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
/**
* Base class for {@link ActionDisabledByAdminController} implementations.
*/
abstract class BaseActionDisabledByAdminController
implements ActionDisabledByAdminController {
protected @UserIdInt int mEnforcementAdminUserId;
protected EnforcedAdmin mEnforcedAdmin;
protected ActionDisabledLearnMoreButtonLauncher mLauncher;
protected final DeviceAdminStringProvider mStringProvider;
BaseActionDisabledByAdminController(DeviceAdminStringProvider stringProvider) {
mStringProvider = stringProvider;
}
@Override
public final void initialize(ActionDisabledLearnMoreButtonLauncher launcher) {
mLauncher = requireNonNull(launcher, "launcher cannot be null");
}
@Override
public final void updateEnforcedAdmin(EnforcedAdmin admin, int adminUserId) {
assertInitialized();
mEnforcementAdminUserId = adminUserId;
mEnforcedAdmin = requireNonNull(admin, "admin cannot be null");
}
protected final void assertInitialized() {
Preconditions.checkState(mLauncher != null, "must call initialize() first");
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
public class BiometricActionDisabledByAdminController extends BaseActionDisabledByAdminController {
private static final String TAG = "BiometricActionDisabledByAdminController";
BiometricActionDisabledByAdminController(
DeviceAdminStringProvider stringProvider) {
super(stringProvider);
}
@Override
public void setupLearnMoreButton(Context context) {
}
@Override
public String getAdminSupportTitle(@Nullable String restriction) {
return mStringProvider.getDisabledBiometricsParentConsentTitle();
}
@Override
public CharSequence getAdminSupportContentString(Context context,
@Nullable CharSequence supportMessage) {
return mStringProvider.getDisabledBiometricsParentConsentContent();
}
@Override
public DialogInterface.OnClickListener getPositiveButtonListener(@NonNull Context context,
@NonNull RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
return (dialog, which) -> {
Log.d(TAG, "Positive button clicked, component: " + enforcedAdmin.component);
final Intent intent = new Intent(Settings.ACTION_MANAGE_SUPERVISOR_RESTRICTED_SETTING)
.putExtra(Settings.EXTRA_SUPERVISOR_RESTRICTED_SETTING_KEY,
Settings.SUPERVISOR_VERIFICATION_SETTING_BIOMETRICS)
.setData(new Uri.Builder()
.scheme("policy")
.appendPath("biometric")
.build())
.setPackage(enforcedAdmin.component.getPackageName());
context.startActivity(intent);
};
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
/**
* A {@code String} provider for the action disabled by admin dialog.
*/
public interface DeviceAdminStringProvider {
/**
* Returns the default dialog title for the case when an action is disabled by policy on a
* managed device.
*/
String getDefaultDisabledByPolicyTitle();
/**
* Returns the dialog title for the case when volume adjusting is disabled.
*/
String getDisallowAdjustVolumeTitle();
/**
* Returns the dialog title for the case when outgoing calls are disabled.
*/
String getDisallowOutgoingCallsTitle();
/**
* Returns the dialog title for the case when sending SMS is disabled.
*/
String getDisallowSmsTitle();
/**
* Returns the dialog title for the case when the camera is disabled.
*/
String getDisableCameraTitle();
/**
* Returns the dialog title for the case when screen capturing is disabled.
*/
String getDisableScreenCaptureTitle();
/**
* Returns the dialog title for the case when suspending apps is disabled.
*/
String getSuspendPackagesTitle();
/**
* Returns the default dialog content for the case when an action is disabled by policy.
*/
String getDefaultDisabledByPolicyContent();
/**
* Returns the URL for the page to be shown when the learn more button is chosen.
*/
String getLearnMoreHelpPageUrl();
/**
* Returns the default dialog title for the case when an action is disabled by policy on
* a financed device.
*/
String getDisabledByPolicyTitleForFinancedDevice();
/**
* Returns the dialog title for when biometrics require parental consent.
*/
String getDisabledBiometricsParentConsentTitle();
/**
* Returns the dialog title when the setting is blocked by supervision app.
*/
String getDisabledByParentContent();
/**
* Returns the dialog contents for when biometrics require parental consent.
*/
String getDisabledBiometricsParentConsentContent();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import android.content.Context;
import androidx.annotation.Nullable;
/**
* An {@link ActionDisabledByAdminController} to be used with financed devices.
*/
final class FinancedDeviceActionDisabledByAdminController
extends BaseActionDisabledByAdminController {
FinancedDeviceActionDisabledByAdminController(DeviceAdminStringProvider stringProvider) {
super(stringProvider);
}
@Override
public void setupLearnMoreButton(Context context) {
assertInitialized();
mLauncher.setupLearnMoreButtonToShowAdminPolicies(context, mEnforcementAdminUserId,
mEnforcedAdmin);
}
@Override
public String getAdminSupportTitle(@Nullable String restriction) {
return mStringProvider.getDisabledByPolicyTitleForFinancedDevice();
}
@Override
public CharSequence getAdminSupportContentString(Context context, CharSequence supportMessage) {
return supportMessage;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import static java.util.Objects.requireNonNull;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.Nullable;
import com.android.settingslib.enterprise.ActionDisabledLearnMoreButtonLauncher.ResolveActivityChecker;
/**
* An {@link ActionDisabledByAdminController} to be used with managed devices.
*/
final class ManagedDeviceActionDisabledByAdminController
extends BaseActionDisabledByAdminController {
interface ForegroundUserChecker {
boolean isUserForeground(Context context, UserHandle userHandle);
}
public final static ForegroundUserChecker DEFAULT_FOREGROUND_USER_CHECKER =
ManagedDeviceActionDisabledByAdminController::isUserForeground;
/**
* The {@link UserHandle} which is preferred for launching the web help page in
* <p>If not able to launch the web help page in this user, the current user will be used as
* fallback instead. If the current user cannot open it either, the admin policies page will
* be used instead.
*/
private final UserHandle mPreferredUserHandle;
private final ForegroundUserChecker mForegroundUserChecker;
private final ResolveActivityChecker mResolveActivityChecker;
/**
* Constructs a {@link ManagedDeviceActionDisabledByAdminController}
* @param preferredUserHandle - user on which to launch the help web page, if necessary
*/
ManagedDeviceActionDisabledByAdminController(
DeviceAdminStringProvider stringProvider,
UserHandle preferredUserHandle,
ForegroundUserChecker foregroundUserChecker,
ResolveActivityChecker resolveActivityChecker) {
super(stringProvider);
mPreferredUserHandle = requireNonNull(preferredUserHandle);
mForegroundUserChecker = requireNonNull(foregroundUserChecker);
mResolveActivityChecker = requireNonNull(resolveActivityChecker);
}
/**
* We don't show Learn More button in Admin-Support Dialog anymore.
*/
@Override
public void setupLearnMoreButton(Context context) {
}
private static boolean isUserForeground(Context context, UserHandle userHandle) {
return context.createContextAsUser(userHandle, /* flags= */ 0)
.getSystemService(UserManager.class).isUserForeground();
}
@Override
public String getAdminSupportTitle(@Nullable String restriction) {
return mStringProvider.getDefaultDisabledByPolicyTitle();
}
@Override
public CharSequence getAdminSupportContentString(Context context, CharSequence supportMessage) {
return supportMessage != null
? supportMessage
: mStringProvider.getDefaultDisabledByPolicyContent();
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settingslib.enterprise;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
final class SupervisedDeviceActionDisabledByAdminController
extends BaseActionDisabledByAdminController {
private static final String TAG = "SupervisedDeviceActionDisabledByAdminController";
private final String mRestriction;
SupervisedDeviceActionDisabledByAdminController(
DeviceAdminStringProvider stringProvider, String restriction) {
super(stringProvider);
mRestriction = restriction;
}
@Override
public void setupLearnMoreButton(Context context) {
}
@Override
public String getAdminSupportTitle(@Nullable String restriction) {
return mStringProvider.getDisabledBiometricsParentConsentTitle();
}
@Override
public CharSequence getAdminSupportContentString(Context context,
@Nullable CharSequence supportMessage) {
return mStringProvider.getDisabledByParentContent();
}
@Nullable
@Override
public DialogInterface.OnClickListener getPositiveButtonListener(@NonNull Context context,
@NonNull RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
if (enforcedAdmin.component == null
|| TextUtils.isEmpty(enforcedAdmin.component.getPackageName())) {
return null;
}
final Intent intent = new Intent(Settings.ACTION_MANAGE_SUPERVISOR_RESTRICTED_SETTING)
.setData(new Uri.Builder()
.scheme("policy")
.appendPath("user_restrictions")
.appendPath(mRestriction)
.build())
.setPackage(enforcedAdmin.component.getPackageName());
ComponentName resolvedSupervisionActivity =
intent.resolveActivity(context.getPackageManager());
if (resolvedSupervisionActivity == null) {
return null;
}
return (dialog, which) -> {
context.startActivity(intent);
};
}
}