Make "Action not allowed" dialog compliant with Material Spec and replace full screen activities with the dialog.

Bug: 64893948
Test: make ROBOTEST_FILTER=ActionDisabledByAdminDialogTest -j40 RunSettingsRoboTests
Test: make ROBOTEST_FILTER=ActionDisabledByAdminDialogHelperTest -j40 RunSettingsRoboTests
Change-Id: I9308d8d86a3789b8f2c92b9f4f20cf00cce71d14
This commit is contained in:
arangelov
2017-10-27 13:51:28 +01:00
committed by Antoan Angelov
parent 22a39c2b93
commit e35badd9d5
24 changed files with 735 additions and 335 deletions

View File

@@ -2955,7 +2955,7 @@
android:value="com.android.settings.applications.appinfo.ExternalSourcesDetails" />
</activity>
<activity android:name="ShowAdminSupportDetailsDialog"
<activity android:name=".enterprise.ActionDisabledByAdminDialog"
android:theme="@style/Transparent"
android:excludeFromRecents="true"
android:launchMode="singleTop">

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:id="@+id/admin_support_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:text="@string/default_admin_support_msg"
android:maxLength="200"
android:autoLink="email|phone|web"
android:textColor="?android:attr/textColorSecondary" />
<TextView android:id="@+id/admins_policies_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/admin_details_dialog_link_padding_top"
android:text="@string/admin_support_more_info"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="?android:attr/colorAccent"
android:clickable="true"
android:background="?android:attr/selectableItemBackground" />
</merge>

View File

@@ -23,7 +23,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingBottom="@dimen/admin_details_dialog_padding">
android:paddingBottom="@dimen/admin_details_dialog_title_bottom_padding">
<ImageView android:id="@+id/admin_support_icon"
android:layout_width="@dimen/admin_details_dialog_icon_size"
android:layout_height="@dimen/admin_details_dialog_icon_size"
@@ -46,7 +46,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/admin_support_details_content" />
<TextView android:id="@+id/admin_support_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:text="@string/default_admin_support_msg"
android:maxLength="200"
android:autoLink="email|phone|web"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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.
-->
<!-- Layout used for displaying admin support details in empty preference fragments. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/admin_support_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@*android:dimen/preference_fragment_padding_side"
android:gravity="center_vertical"
android:orientation="vertical"
android:visibility="gone">
<include layout="@layout/admin_support_details_content" />
</LinearLayout>

View File

@@ -62,8 +62,6 @@
android:gravity="center_vertical"
android:visibility="gone" />
<include layout="@layout/admin_support_details_empty_view" />
<RelativeLayout android:id="@+id/button_bar"
android:layout_height="wrap_content"
android:layout_width="match_parent"

View File

@@ -239,8 +239,12 @@
<!-- Admin support contact details dialog. -->
<dimen name="admin_details_dialog_padding">24dp</dimen>
<dimen name="admin_details_dialog_title_bottom_padding">20dp</dimen>
<dimen name="admin_details_dialog_icon_size">48dp</dimen>
<dimen name="admin_details_dialog_link_padding_top">36dp</dimen>
<dimen name="admin_details_dialog_learn_more_button_top_margin">24dp</dimen>
<dimen name="admin_details_dialog_learn_more_button_padding">8dp</dimen>
<dimen name="admin_details_dialog_learn_more_button_minWidth">88dp</dimen>
<!-- Button bar padding for unmount button. -->
<dimen name="unmount_button_padding">8dp</dimen>

View File

@@ -57,6 +57,7 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtils;
@@ -503,10 +504,11 @@ public class MasterClear extends InstrumentedFragment implements OnGlobalLayoutL
if (disallow && !Utils.isDemoUser(context)) {
return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
} else if (admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
view.setVisibility(View.VISIBLE);
return view;
new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin)
.setOnDismissListener(__ -> getActivity().finish())
.show();
return new View(getContext());
}
mContentView = inflater.inflate(R.layout.master_clear, null);

View File

@@ -34,6 +34,7 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settingslib.RestrictedLockUtils;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -151,10 +152,11 @@ public class MasterClearConfirm extends InstrumentedFragment {
UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {
return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
} else if (admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
view.setVisibility(View.VISIBLE);
return view;
new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin)
.setOnDismissListener(__ -> getActivity().finish())
.show();
return new View(getActivity());
}
mContentView = inflater.inflate(R.layout.master_clear_confirm, null);
establishFinalConfirmationState();
@@ -167,9 +169,9 @@ public class MasterClearConfirm extends InstrumentedFragment {
TextView confirmationMessage =
(TextView) mContentView.findViewById(R.id.master_clear_confirm);
if (confirmationMessage != null) {
String accessibileText = new StringBuilder(currentTitle).append(",").append(
String accessibleText = new StringBuilder(currentTitle).append(",").append(
confirmationMessage.getText()).toString();
getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibileText));
getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibleText));
}
}

View File

@@ -45,6 +45,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtils;
@@ -245,10 +246,11 @@ public class ResetNetwork extends InstrumentedFragment {
UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
} else if (admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
view.setVisibility(View.VISIBLE);
return view;
new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
.setOnDismissListener(__ -> getActivity().finish())
.show();
return new View(getContext());
}
mContentView = inflater.inflate(R.layout.reset_network, null);

View File

@@ -27,7 +27,6 @@ import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RecoverySystem;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
@@ -42,6 +41,7 @@ import android.widget.Toast;
import com.android.ims.ImsManager;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settings.wrapper.RecoverySystemWrapper;
import com.android.settings.core.InstrumentedFragment;
import com.android.settingslib.RestrictedLockUtils;
@@ -197,10 +197,11 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
} else if (admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
view.setVisibility(View.VISIBLE);
return view;
new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
.setOnDismissListener(__ -> getActivity().finish())
.show();
return new View(getContext());
}
mContentView = inflater.inflate(R.layout.reset_network_confirm, null);
establishFinalConfirmationState();

View File

@@ -17,6 +17,7 @@
package com.android.settings;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +31,7 @@ import android.view.View;
import android.widget.TextView;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settingslib.RestrictedLockUtils;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -67,7 +69,6 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
private RestrictionsManager mRestrictionsManager;
private final String mRestrictionKey;
private View mAdminSupportDetails;
private EnforcedAdmin mEnforcedAdmin;
private TextView mEmptyTextView;
@@ -85,6 +86,8 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
}
};
private AlertDialog mActionDisabledDialog;
/**
* @param restrictionKey The restriction key to check before pin protecting
* this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
@@ -116,7 +119,6 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdminSupportDetails = initAdminSupportDetailsView();
mEmptyTextView = initEmptyTextView();
}
@@ -204,10 +206,6 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
return restricted && mRestrictionsManager.hasRestrictionsProvider();
}
private View initAdminSupportDetailsView() {
return getActivity().findViewById(R.id.admin_support_details);
}
protected TextView initEmptyTextView() {
TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
return emptyView;
@@ -229,11 +227,14 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
@Override
protected void onDataSetChanged() {
highlightPreferenceIfNeeded();
if (mAdminSupportDetails != null && isUiRestrictedByOnlyAdmin()) {
if (isUiRestrictedByOnlyAdmin()
&& (mActionDisabledDialog == null || !mActionDisabledDialog.isShowing())) {
final EnforcedAdmin admin = getRestrictionEnforcedAdmin();
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(),
mAdminSupportDetails, admin, false);
setEmptyView(mAdminSupportDetails);
mActionDisabledDialog = new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(mRestrictionKey, admin)
.setOnDismissListener(__ -> getActivity().finish())
.show();
setEmptyView(new View(getContext()));
} else if (mEmptyTextView != null) {
setEmptyView(mEmptyTextView);
}

View File

@@ -1,222 +0,0 @@
/*
* Copyright (C) 2015 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.settings;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import java.util.Objects;
public class ShowAdminSupportDetailsDialog extends Activity
implements DialogInterface.OnDismissListener {
private static final String TAG = "AdminSupportDialog";
private EnforcedAdmin mEnforcedAdmin;
private View mDialogView;
private String mRestriction = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mEnforcedAdmin = getAdminDetailsFromIntent(getIntent());
mRestriction = getRestrictionFromIntent(getIntent());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
mDialogView = LayoutInflater.from(builder.getContext()).inflate(
R.layout.admin_support_details_dialog, null);
initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
mRestriction);
builder.setOnDismissListener(this)
.setPositiveButton(R.string.okay, null)
.setView(mDialogView)
.show();
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
EnforcedAdmin admin = getAdminDetailsFromIntent(intent);
String restriction = getRestrictionFromIntent(intent);
if (!mEnforcedAdmin.equals(admin) || !Objects.equals(mRestriction, restriction)) {
mEnforcedAdmin = admin;
mRestriction = restriction;
initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
mRestriction);
}
}
private EnforcedAdmin getAdminDetailsFromIntent(Intent intent) {
EnforcedAdmin admin = new EnforcedAdmin(null, UserHandle.myUserId());
if (intent == null) {
return admin;
}
admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
admin.userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
return admin;
}
private String getRestrictionFromIntent(Intent intent) {
if (intent == null) return null;
return intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION);
}
private void initializeDialogViews(View root, ComponentName admin, int userId,
String restriction) {
if (admin != null) {
if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(this, admin)
|| !RestrictedLockUtils.isCurrentUserOrProfile(this, userId)) {
admin = null;
} else {
ActivityInfo ai = null;
try {
ai = AppGlobals.getPackageManager().getReceiverInfo(admin, 0 /* flags */,
userId);
} catch (RemoteException e) {
Log.w(TAG, "Missing reciever info", e);
}
if (ai != null) {
Drawable icon = ai.loadIcon(getPackageManager());
Drawable badgedIcon = getPackageManager().getUserBadgedIcon(
icon, new UserHandle(userId));
((ImageView) root.findViewById(R.id.admin_support_icon)).setImageDrawable(
badgedIcon);
}
}
}
setAdminSupportTitle(root, restriction);
setAdminSupportDetails(this, root, new EnforcedAdmin(admin, userId), true);
}
private void setAdminSupportTitle(View root, String restriction) {
final TextView titleView = (TextView) root.findViewById(R.id.admin_support_dialog_title);
if (titleView == null) {
return;
}
if (restriction == null) {
titleView.setText(R.string.disabled_by_policy_title);
return;
}
switch(restriction) {
case UserManager.DISALLOW_ADJUST_VOLUME:
titleView.setText(R.string.disabled_by_policy_title_adjust_volume);
break;
case UserManager.DISALLOW_OUTGOING_CALLS:
titleView.setText(R.string.disabled_by_policy_title_outgoing_calls);
break;
case UserManager.DISALLOW_SMS:
titleView.setText(R.string.disabled_by_policy_title_sms);
break;
case DevicePolicyManager.POLICY_DISABLE_CAMERA:
titleView.setText(R.string.disabled_by_policy_title_camera);
break;
case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE:
titleView.setText(R.string.disabled_by_policy_title_screen_capture);
break;
case DevicePolicyManager.POLICY_MANDATORY_BACKUPS:
titleView.setText(R.string.disabled_by_policy_title_turn_off_backups);
break;
default:
// Use general text if no specialized title applies
titleView.setText(R.string.disabled_by_policy_title);
}
}
public static void setAdminSupportDetails(final Activity activity, View root,
final EnforcedAdmin enforcedAdmin, final boolean finishActivity) {
if (enforcedAdmin == null) {
return;
}
if (enforcedAdmin.component != null) {
DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(activity,
enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile(
activity, enforcedAdmin.userId)) {
enforcedAdmin.component = null;
} else {
if (enforcedAdmin.userId == UserHandle.USER_NULL) {
enforcedAdmin.userId = UserHandle.myUserId();
}
CharSequence supportMessage = null;
if (UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID)) {
supportMessage = dpm.getShortSupportMessageForUser(
enforcedAdmin.component, enforcedAdmin.userId);
}
if (supportMessage != null) {
TextView textView = (TextView) root.findViewById(R.id.admin_support_msg);
textView.setText(supportMessage);
}
}
}
root.findViewById(R.id.admins_policies_list).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
if (enforcedAdmin.component != null) {
intent.setClass(activity, DeviceAdminAdd.class);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
enforcedAdmin.component);
intent.putExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, true);
// DeviceAdminAdd class may need to run as managed profile.
activity.startActivityAsUser(intent,
new UserHandle(enforcedAdmin.userId));
} else {
intent.setClass(activity, Settings.DeviceAdminSettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Activity merges both managed profile and parent users
// admins so show as same user as this activity.
activity.startActivity(intent);
}
if (finishActivity) {
activity.finish();
}
}
});
}
@Override
public void onDismiss(DialogInterface dialog) {
finish();
}
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.dashboard;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,9 +32,9 @@ import android.os.UserManager;
import android.view.View;
import android.widget.TextView;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.ShowAdminSupportDetailsDialog;
import com.android.settingslib.RestrictedLockUtils;
/**
@@ -69,7 +70,6 @@ public abstract class RestrictedDashboardFragment extends DashboardFragment {
private RestrictionsManager mRestrictionsManager;
private final String mRestrictionKey;
private View mAdminSupportDetails;
private EnforcedAdmin mEnforcedAdmin;
private TextView mEmptyTextView;
@@ -86,6 +86,7 @@ public abstract class RestrictedDashboardFragment extends DashboardFragment {
}
}
};
private AlertDialog mActionDisabledDialog;
/**
* @param restrictionKey The restriction key to check before pin protecting
@@ -118,7 +119,6 @@ public abstract class RestrictedDashboardFragment extends DashboardFragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdminSupportDetails = initAdminSupportDetailsView();
mEmptyTextView = initEmptyTextView();
}
@@ -206,10 +206,6 @@ public abstract class RestrictedDashboardFragment extends DashboardFragment {
return restricted && mRestrictionsManager.hasRestrictionsProvider();
}
private View initAdminSupportDetailsView() {
return getActivity().findViewById(R.id.admin_support_details);
}
protected TextView initEmptyTextView() {
TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
return emptyView;
@@ -231,11 +227,14 @@ public abstract class RestrictedDashboardFragment extends DashboardFragment {
@Override
protected void onDataSetChanged() {
highlightPreferenceIfNeeded();
if (mAdminSupportDetails != null && isUiRestrictedByOnlyAdmin()) {
if (isUiRestrictedByOnlyAdmin()
&& (mActionDisabledDialog == null || !mActionDisabledDialog.isShowing())) {
final EnforcedAdmin admin = getRestrictionEnforcedAdmin();
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(),
mAdminSupportDetails, admin, false);
setEmptyView(mAdminSupportDetails);
mActionDisabledDialog = new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(mRestrictionKey, admin)
.setOnDismissListener(__ -> getActivity().finish())
.show();
setEmptyView(new View(getContext()));
} else if (mEmptyTextView != null) {
setEmptyView(mEmptyTextView);
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 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.settings.enterprise;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
public class ActionDisabledByAdminDialog extends Activity
implements DialogInterface.OnDismissListener {
private ActionDisabledByAdminDialogHelper mDialogHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
getAdminDetailsFromIntent(getIntent());
final String restriction = getRestrictionFromIntent(getIntent());
mDialogHelper = new ActionDisabledByAdminDialogHelper(this);
mDialogHelper.prepareDialogBuilder(restriction, enforcedAdmin)
.setOnDismissListener(this)
.show();
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
final EnforcedAdmin admin = getAdminDetailsFromIntent(intent);
final String restriction = getRestrictionFromIntent(intent);
mDialogHelper.updateDialog(restriction, admin);
}
@android.support.annotation.VisibleForTesting
EnforcedAdmin getAdminDetailsFromIntent(Intent intent) {
final EnforcedAdmin admin = new EnforcedAdmin(null, UserHandle.myUserId());
if (intent == null) {
return admin;
}
admin.component = intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
admin.userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
return admin;
}
@android.support.annotation.VisibleForTesting
String getRestrictionFromIntent(Intent intent) {
if (intent == null) return null;
return intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION);
}
@Override
public void onDismiss(DialogInterface dialog) {
finish();
}
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright (C) 2018 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.settings.enterprise;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.drawable.Drawable;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import java.util.Objects;
/**
* Helper class for {@link ActionDisabledByAdminDialog} which sets up the dialog.
*/
public class ActionDisabledByAdminDialogHelper {
private static final String TAG = ActionDisabledByAdminDialogHelper.class.getName();
private EnforcedAdmin mEnforcedAdmin;
private ViewGroup mDialogView;
private String mRestriction = null;
private Activity mActivity;
public ActionDisabledByAdminDialogHelper(Activity activity) {
mActivity = activity;
}
public AlertDialog.Builder prepareDialogBuilder(String restriction,
EnforcedAdmin enforcedAdmin) {
mEnforcedAdmin = enforcedAdmin;
mRestriction = restriction;
final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
mDialogView = (ViewGroup) LayoutInflater.from(builder.getContext()).inflate(
R.layout.admin_support_details_dialog, null);
initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
mRestriction);
return builder
.setPositiveButton(R.string.okay, null)
.setNeutralButton(R.string.admin_more_details,
(dialog, which) -> {
showAdminPolicies(mEnforcedAdmin, mActivity);
mActivity.finish();
})
.setView(mDialogView);
}
public void updateDialog(String restriction, EnforcedAdmin admin) {
if (mEnforcedAdmin.equals(admin) && Objects.equals(mRestriction, restriction)) {
return;
}
mEnforcedAdmin = admin;
mRestriction = restriction;
initializeDialogViews(mDialogView, mEnforcedAdmin.component, mEnforcedAdmin.userId,
mRestriction);
}
private void initializeDialogViews(View root, ComponentName admin, int userId,
String restriction) {
if (admin == null) {
return;
}
if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(mActivity, admin)
|| !RestrictedLockUtils.isCurrentUserOrProfile(mActivity, userId)) {
admin = null;
} else {
ActivityInfo ai = null;
try {
ai = AppGlobals.getPackageManager().getReceiverInfo(admin, 0 /* flags */,
userId);
} catch (RemoteException e) {
Log.w(TAG, "Missing reciever info", e);
}
if (ai != null) {
final Drawable icon = ai.loadIcon(mActivity.getPackageManager());
final Drawable badgedIcon = mActivity.getPackageManager().getUserBadgedIcon(
icon, new UserHandle(userId));
((ImageView) root.findViewById(R.id.admin_support_icon)).setImageDrawable(
badgedIcon);
}
}
setAdminSupportTitle(root, restriction);
setAdminSupportDetails(mActivity, root, new EnforcedAdmin(admin, userId));
}
@VisibleForTesting
void setAdminSupportTitle(View root, String restriction) {
final TextView titleView = root.findViewById(R.id.admin_support_dialog_title);
if (titleView == null) {
return;
}
if (restriction == null) {
titleView.setText(R.string.disabled_by_policy_title);
return;
}
switch (restriction) {
case UserManager.DISALLOW_ADJUST_VOLUME:
titleView.setText(R.string.disabled_by_policy_title_adjust_volume);
break;
case UserManager.DISALLOW_OUTGOING_CALLS:
titleView.setText(R.string.disabled_by_policy_title_outgoing_calls);
break;
case UserManager.DISALLOW_SMS:
titleView.setText(R.string.disabled_by_policy_title_sms);
break;
case DevicePolicyManager.POLICY_DISABLE_CAMERA:
titleView.setText(R.string.disabled_by_policy_title_camera);
break;
case DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE:
titleView.setText(R.string.disabled_by_policy_title_screen_capture);
break;
case DevicePolicyManager.POLICY_MANDATORY_BACKUPS:
titleView.setText(R.string.disabled_by_policy_title_turn_off_backups);
break;
default:
// Use general text if no specialized title applies
titleView.setText(R.string.disabled_by_policy_title);
}
}
@VisibleForTesting
void setAdminSupportDetails(final Activity activity, final View root,
final EnforcedAdmin enforcedAdmin) {
if (enforcedAdmin == null || enforcedAdmin.component == null) {
return;
}
final DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (!RestrictedLockUtils.isAdminInCurrentUserOrProfile(activity,
enforcedAdmin.component) || !RestrictedLockUtils.isCurrentUserOrProfile(
activity, enforcedAdmin.userId)) {
enforcedAdmin.component = null;
} else {
if (enforcedAdmin.userId == UserHandle.USER_NULL) {
enforcedAdmin.userId = UserHandle.myUserId();
}
CharSequence supportMessage = null;
if (UserHandle.isSameApp(Process.myUid(), Process.SYSTEM_UID)) {
supportMessage = dpm.getShortSupportMessageForUser(
enforcedAdmin.component, enforcedAdmin.userId);
}
if (supportMessage != null) {
final TextView textView = root.findViewById(R.id.admin_support_msg);
textView.setText(supportMessage);
}
}
}
@VisibleForTesting
void showAdminPolicies(final EnforcedAdmin enforcedAdmin, final Activity activity) {
final Intent intent = new Intent();
if (enforcedAdmin.component != null) {
intent.setClass(activity, DeviceAdminAdd.class);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
enforcedAdmin.component);
intent.putExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, true);
// DeviceAdminAdd class may need to run as managed profile.
activity.startActivityAsUser(intent,
new UserHandle(enforcedAdmin.userId));
} else {
intent.setClass(activity, Settings.DeviceAdminSettingsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Activity merges both managed profile and parent users
// admins so show as same user as this activity.
activity.startActivity(intent);
}
}
}

View File

@@ -1,4 +1,7 @@
# Default reviewers for this and subdirectories.
sandness@google.com
tonymak@google.com
yuemingw@google.com
arangelov@google.com
# Emergency approvers in case the above are not available

View File

@@ -28,11 +28,11 @@ import android.view.ViewGroup;
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settingslib.HelpUtils;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.ShowAdminSupportDetailsDialog;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.RestrictedLockUtils;
@@ -70,11 +70,10 @@ public class AndroidBeam extends InstrumentedFragment
mBeamDisallowedByBase = RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId());
if (!mBeamDisallowedByBase && admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
ShowAdminSupportDetailsDialog.setAdminSupportDetails(getActivity(), view, admin, false);
view.setVisibility(View.VISIBLE);
new ActionDisabledByAdminDialogHelper(getActivity())
.prepareDialogBuilder(UserManager.DISALLOW_OUTGOING_BEAM, admin).show();
mBeamDisallowedByOnlyAdmin = true;
return view;
return new View(getContext());
}
mView = inflater.inflate(R.layout.android_beam, container, false);
return mView;

View File

@@ -0,0 +1,186 @@
/*
* Copyright (C) 2018 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.settings.enterprise;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.os.Process;
import android.os.UserManager;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.testutils.CustomActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowActivity;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowProcess;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {
ShadowDevicePolicyManager.class,
ShadowUserManager.class,
ShadowActivity.class,
ShadowProcess.class
})
public class ActionDisabledByAdminDialogHelperTest {
private ActionDisabledByAdminDialogHelper mHelper;
private Activity mActivity;
private org.robolectric.shadows.ShadowActivity mActivityShadow;
@Before
public void setUp() {
mActivity = Robolectric.buildActivity(CustomActivity.class).get();
mActivityShadow = Shadow.extract(mActivity);
mHelper = new ActionDisabledByAdminDialogHelper(mActivity);
}
@Test
public void testShowAdminPoliciesWithComponent() {
final int userId = 123;
final ComponentName component = new ComponentName("some.package.name",
"some.package.name.SomeClass");
final EnforcedAdmin admin = new EnforcedAdmin(component, userId);
mHelper.showAdminPolicies(admin, mActivity);
final Intent intent = mActivityShadow.getNextStartedActivity();
assertTrue(
intent.getBooleanExtra(DeviceAdminAdd.EXTRA_CALLED_FROM_SUPPORT_DIALOG, false));
assertEquals(component,
intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN));
}
@Test
public void testShowAdminPoliciesWithoutComponent() {
final int userId = 123;
final EnforcedAdmin admin = new EnforcedAdmin(null, userId);
mHelper.showAdminPolicies(admin, mActivity);
final Intent intent = mActivityShadow.getNextStartedActivity();
assertEquals(intent.getComponent(), new ComponentName(mActivity,
Settings.DeviceAdminSettingsActivity.class.getName()));
}
@Test
public void testSetAdminSupportTitle() {
final ViewGroup view = new FrameLayout(mActivity);
final TextView textView = new TextView(mActivity);
textView.setId(R.id.admin_support_dialog_title);
view.addView(textView);
mHelper.setAdminSupportTitle(view, UserManager.DISALLOW_ADJUST_VOLUME);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title_adjust_volume));
mHelper.setAdminSupportTitle(view, UserManager.DISALLOW_OUTGOING_CALLS);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title_outgoing_calls));
mHelper.setAdminSupportTitle(view, UserManager.DISALLOW_SMS);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title_sms));
mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_DISABLE_CAMERA);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title_camera));
mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title_screen_capture));
mHelper.setAdminSupportTitle(view, DevicePolicyManager.POLICY_MANDATORY_BACKUPS);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title_turn_off_backups));
mHelper.setAdminSupportTitle(view, "another restriction");
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title));
mHelper.setAdminSupportTitle(view, null);
assertEquals(Shadows.shadowOf(textView).innerText(),
mActivity.getString(R.string.disabled_by_policy_title));
}
@Test
public void testSetAdminSupportDetails() {
final DevicePolicyManager dpm = RuntimeEnvironment.application.getSystemService(
DevicePolicyManager.class);
final ShadowDevicePolicyManager dpmShadow = Shadow.extract(dpm);
final UserManager userManager = RuntimeEnvironment.application.getSystemService(
UserManager.class);
final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
final ViewGroup view = new FrameLayout(mActivity);
final ComponentName component = new ComponentName("some.package.name",
"some.package.name.SomeClass");
final EnforcedAdmin admin = new EnforcedAdmin(component, 123);
final TextView textView = new TextView(mActivity);
textView.setId(R.id.admin_support_msg);
view.addView(textView);
dpmShadow.setShortSupportMessageForUser(component, 123, "some message");
dpmShadow.setIsAdminActiveAsUser(true);
userManagerShadow.addProfile(new UserInfo(123, null, 0));
ShadowProcess.setMyUid(Process.SYSTEM_UID);
mHelper.setAdminSupportDetails(mActivity, view, admin);
assertNotNull(admin.component);
assertEquals("some message", Shadows.shadowOf(textView).innerText());
}
@Test
public void testSetAdminSupportDetailsNotAdmin() {
final DevicePolicyManager dpm = RuntimeEnvironment.application.getSystemService(
DevicePolicyManager.class);
final ShadowDevicePolicyManager dpmShadow = Shadow.extract(dpm);
final UserManager userManager = RuntimeEnvironment.application.getSystemService(
UserManager.class);
final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
final ComponentName component = new ComponentName("some.package.name",
"some.package.name.SomeClass");
final EnforcedAdmin admin = new EnforcedAdmin(component, 123);
dpmShadow.setShortSupportMessageForUser(component, 123, "some message");
dpmShadow.setIsAdminActiveAsUser(false);
userManagerShadow.addProfile(new UserInfo(123, null, 0));
mHelper.setAdminSupportDetails(mActivity, null, admin);
assertNull(admin.component);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 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.settings.enterprise;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.UserHandle;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(SettingsRobolectricTestRunner.class)
public class ActionDisabledByAdminDialogTest {
private ActionDisabledByAdminDialog mDialog;
@Before
public void setUp() {
mDialog = new ActionDisabledByAdminDialog();
}
@Test
public void testGetAdminDetailsFromIntent() {
final int userId = 123;
final ComponentName component = new ComponentName("com.some.package", ".SomeClass");
final EnforcedAdmin expectedAdmin = new EnforcedAdmin(component, userId);
final Intent intent = new Intent();
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, component);
intent.putExtra(Intent.EXTRA_USER_ID, userId);
Assert.assertEquals(expectedAdmin, mDialog.getAdminDetailsFromIntent(intent));
}
@Test
public void testGetAdminDetailsFromNullIntent() {
final int userId = UserHandle.myUserId();
final EnforcedAdmin expectedAdmin = new EnforcedAdmin(null, userId);
Assert.assertEquals(expectedAdmin, mDialog.getAdminDetailsFromIntent(null));
}
@Test
public void testGetRestrictionFromIntent() {
final String restriction = "someRestriction";
final Intent intent = new Intent();
intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction);
Assert.assertEquals(restriction, mDialog.getRestrictionFromIntent(intent));
}
@Test
public void testGetRestrictionFromNullIntent() {
Assert.assertEquals(null, mDialog.getRestrictionFromIntent(null));
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2018 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.settings.testutils;
import android.app.Activity;
import android.content.Intent;
import android.os.UserHandle;
public class CustomActivity extends Activity {
@Override
public void startActivityAsUser(Intent intent, UserHandle user) {}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2018 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.settings.testutils.shadow;
import android.content.Intent;
import android.os.UserHandle;
import com.android.settings.testutils.CustomActivity;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowApplication;
@Implements(CustomActivity.class)
public class ShadowActivity extends org.robolectric.shadows.ShadowActivity {
@Implementation
public void startActivityAsUser(Intent intent, UserHandle user) {
ShadowApplication.getInstance().startActivity(intent);
}
}

View File

@@ -0,0 +1,41 @@
package com.android.settings.testutils.shadow;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* This shadow if using {@link ShadowDevicePolicyManagerWrapper} is not possible.
*/
@Implements(DevicePolicyManager.class)
public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDevicePolicyManager {
private Map<Integer, CharSequence> mSupportMessagesMap = new HashMap<>();
private boolean mIsAdminActiveAsUser = false;
public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) {
mSupportMessagesMap.put(Objects.hash(admin, userHandle), message);
}
@Implementation
public @Nullable CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
int userHandle) {
return mSupportMessagesMap.get(Objects.hash(admin, userHandle));
}
@Implementation
public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
return mIsAdminActiveAsUser;
}
public void setIsAdminActiveAsUser(boolean active) {
mIsAdminActiveAsUser = active;
}
}

View File

@@ -0,0 +1,18 @@
package com.android.settings.testutils.shadow;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(android.os.Process.class)
public class ShadowProcess {
private static int sUid;
public static void setMyUid(int uid) {
sUid = uid;
}
@Implementation
public static int myUid() {
return sUid;
}
}

View File

@@ -17,7 +17,6 @@
package com.android.settings.testutils.shadow;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
@@ -31,7 +30,6 @@ import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -42,10 +40,12 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
private SparseArray<UserInfo> mUserInfos = new SparseArray<>();
private final List<String> mRestrictions = new ArrayList<>();
private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
private List<UserInfo> mUserProfileInfos = new ArrayList<>();
@Resetter
public void reset() {
mRestrictions.clear();
mUserProfileInfos.clear();
}
public void setUserInfo(int userHandle, UserInfo userInfo) {
@@ -57,9 +57,13 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
return mUserInfos.get(userHandle);
}
public void addProfile(UserInfo userInfo) {
mUserProfileInfos.add(userInfo);
}
@Implementation
public List<UserInfo> getProfiles(@UserIdInt int userHandle) {
return Collections.emptyList();
return mUserProfileInfos;
}
@Implementation