Skip to content

Commit cf793e6

Browse files
author
Alex Johnston
committed
Add factory reset protection policy to TestDPC
* Added new Fragment to create, edit and clear the factory reset protection policy. Bug: 152031262 Test: manual testing Change-Id: Iebf6a248b1e3970825cf2c15993341e84e94b455
1 parent 3f33bd2 commit cf793e6

File tree

6 files changed

+376
-0
lines changed

6 files changed

+376
-0
lines changed
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/*
2+
* Copyright (C) 2020 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.afwsamples.testdpc.policy;
18+
19+
import android.app.AlertDialog;
20+
import android.app.Fragment;
21+
import android.app.admin.DevicePolicyManager;
22+
import android.app.admin.FactoryResetProtectionPolicy;
23+
import android.content.ComponentName;
24+
import android.content.Context;
25+
import android.os.Bundle;
26+
import android.text.TextUtils;
27+
import android.view.LayoutInflater;
28+
import android.view.View;
29+
import android.view.ViewGroup;
30+
import android.widget.AdapterView;
31+
import android.widget.ArrayAdapter;
32+
import android.widget.Button;
33+
import android.widget.EditText;
34+
import android.widget.ListView;
35+
import android.widget.Spinner;
36+
import android.widget.TextView;
37+
import android.widget.Toast;
38+
39+
import androidx.annotation.RequiresApi;
40+
import androidx.annotation.StringRes;
41+
42+
import com.afwsamples.testdpc.DeviceAdminReceiver;
43+
import com.afwsamples.testdpc.R;
44+
import com.afwsamples.testdpc.common.Util;
45+
46+
import java.util.ArrayList;
47+
import java.util.List;
48+
49+
public class FactoryResetProtectionPolicyFragment extends Fragment
50+
implements AdapterView.OnItemSelectedListener, View.OnClickListener {
51+
52+
private static final int DISABLED = 0;
53+
private static final int ENABLED = 1;
54+
55+
private DevicePolicyManager mDevicePolicyManager;
56+
private ComponentName mAdminComponentName;
57+
58+
private List<String> mAccounts = new ArrayList<>();
59+
private boolean mEnabled;
60+
61+
private FrpAccountsAdapter mAccountsAdapter;
62+
private Spinner mFrpEnabledSpinner;
63+
64+
@RequiresApi(api = Util.R_VERSION_CODE)
65+
@Override
66+
public void onCreate(Bundle savedInstanceState) {
67+
mDevicePolicyManager = (DevicePolicyManager)
68+
getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
69+
mAdminComponentName = DeviceAdminReceiver.getComponentName(getActivity());
70+
super.onCreate(savedInstanceState);
71+
getActivity().getActionBar().setTitle(R.string.factory_reset_protection_policy);
72+
}
73+
74+
@RequiresApi(api = Util.R_VERSION_CODE)
75+
@Override
76+
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
77+
Bundle savedInstanceState) {
78+
super.onCreateView(inflater, container, savedInstanceState);
79+
View view = inflater.inflate(R.layout.factory_reset_protection_policy, container, false);
80+
81+
ListView frpAccounts = view.findViewById(R.id.frp_accounts);
82+
mAccountsAdapter = new FrpAccountsAdapter();
83+
frpAccounts.setAdapter(mAccountsAdapter);
84+
85+
Button addAccountButton = view.findViewById(R.id.add_account_button);
86+
addAccountButton.setOnClickListener(this);
87+
Button clearButton = view.findViewById(R.id.clear_frp_button);
88+
clearButton.setOnClickListener(this);
89+
Button saveButton = view.findViewById(R.id.save_frp_button);
90+
saveButton.setOnClickListener(this);
91+
92+
mFrpEnabledSpinner = view.findViewById(R.id.frp_enabled);
93+
mFrpEnabledSpinner.setOnItemSelectedListener(this);
94+
ArrayAdapter<CharSequence> enabledAdapter = ArrayAdapter.createFromResource(getActivity(),
95+
R.array.factory_reset_protection_policy_enabled_choices,
96+
android.R.layout.simple_spinner_item);
97+
enabledAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
98+
mFrpEnabledSpinner.setAdapter(enabledAdapter);
99+
100+
refreshUi();
101+
return view;
102+
}
103+
104+
private void refreshUi() {
105+
mAccountsAdapter.clear();
106+
mFrpEnabledSpinner.setSelection(DISABLED);
107+
108+
FactoryResetProtectionPolicy mFrpPolicy = mDevicePolicyManager
109+
.getFactoryResetProtectionPolicy(mAdminComponentName);
110+
if (mFrpPolicy != null) {
111+
mAccountsAdapter.addAll(mFrpPolicy.getFactoryResetProtectionAccounts());
112+
mFrpEnabledSpinner.setSelection(
113+
mFrpPolicy.isFactoryResetProtectionEnabled() ? ENABLED : DISABLED);
114+
}
115+
}
116+
117+
private class FrpAccountsAdapter extends ArrayAdapter<String> {
118+
119+
public FrpAccountsAdapter() {
120+
super(getActivity(), R.layout.factory_reset_protection_policy_account, mAccounts);
121+
}
122+
123+
@Override
124+
public View getView(int position, View view, ViewGroup parent) {
125+
if (view == null) {
126+
view = getActivity().getLayoutInflater().inflate(
127+
R.layout.factory_reset_protection_policy_account, parent, false);
128+
}
129+
TextView listItemText = view.findViewById(R.id.frp_account);
130+
listItemText.setText(mAccounts.get(position));
131+
132+
Button removeAccountButton = view.findViewById(R.id.remove_account_button);
133+
removeAccountButton.setOnClickListener(v -> {
134+
mAccounts.remove(position);
135+
notifyDataSetChanged();
136+
});
137+
138+
return view;
139+
}
140+
}
141+
142+
@Override
143+
public void onClick(View view) {
144+
switch (view.getId()) {
145+
case R.id.add_account_button:
146+
createAddAccountDialog();
147+
break;
148+
case R.id.clear_frp_button:
149+
mDevicePolicyManager.setFactoryResetProtectionPolicy(mAdminComponentName, null);
150+
refreshUi();
151+
showToast(R.string.cleared_factory_reset_protection_policy);
152+
break;
153+
case R.id.save_frp_button:
154+
mDevicePolicyManager.setFactoryResetProtectionPolicy(mAdminComponentName,
155+
new FactoryResetProtectionPolicy.Builder()
156+
.setFactoryResetProtectionAccounts(mAccounts)
157+
.setFactoryResetProtectionEnabled(mEnabled)
158+
.build());
159+
showToast(R.string.saved_factory_reset_protection_policy);
160+
break;
161+
}
162+
}
163+
164+
public void createAddAccountDialog() {
165+
View view = LayoutInflater.from(getActivity()).inflate(R.layout.simple_edittext, null);
166+
final EditText input = view.findViewById(R.id.input);
167+
168+
final AlertDialog dialog = new AlertDialog.Builder(getActivity())
169+
.setTitle(R.string.add_account)
170+
.setView(view)
171+
.setPositiveButton(android.R.string.ok, null)
172+
.setNegativeButton(android.R.string.cancel, null)
173+
.create();
174+
dialog.setOnShowListener(
175+
dialogInterface -> dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(
176+
okButtonView -> {
177+
String item = input.getText().toString();
178+
if (TextUtils.isEmpty(item)) {
179+
showToast(R.string.fail_to_add_account);
180+
return;
181+
}
182+
mAccountsAdapter.add(item);
183+
dialog.dismiss();
184+
}));
185+
dialog.show();
186+
}
187+
188+
@Override
189+
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
190+
if (parent.getId() == R.id.frp_enabled) {
191+
switch (pos) {
192+
case DISABLED:
193+
mEnabled = false;
194+
break;
195+
case ENABLED:
196+
mEnabled = true;
197+
break;
198+
}
199+
}
200+
}
201+
202+
@Override
203+
public void onNothingSelected(AdapterView<?> adapterView) {
204+
// do nothing
205+
}
206+
207+
private void showToast(@StringRes int stringResId) {
208+
Toast.makeText(getActivity(), stringResId, Toast.LENGTH_LONG).show();
209+
}
210+
211+
}

app/src/main/java/com/afwsamples/testdpc/policy/PolicyManagementFragment.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
396396
private static final String MANAGED_SYSTEM_UPDATES_KEY = "managed_system_updates";
397397
private static final String SET_PRIVATE_DNS_MODE_KEY = "set_private_dns_mode";
398398
private static final String FACTORY_RESET_ORG_OWNED_DEVICE = "factory_reset_org_owned_device";
399+
private static final String SET_FACTORY_RESET_PROTECTION_POLICY_KEY =
400+
"set_factory_reset_protection_policy";
399401
private static final String SET_LOCATION_ENABLED_KEY = "set_location_enabled";
400402
private static final String SET_LOCATION_MODE_KEY = "set_location_mode";
401403
private static final String SUSPEND_PERSONAL_APPS_KEY = "suspend_personal_apps";
@@ -719,6 +721,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
719721

720722
findPreference(CROSS_PROFILE_CALENDAR_KEY).setOnPreferenceClickListener(this);
721723
findPreference(FACTORY_RESET_ORG_OWNED_DEVICE).setOnPreferenceClickListener(this);
724+
findPreference(SET_FACTORY_RESET_PROTECTION_POLICY_KEY).setOnPreferenceClickListener(this);
722725

723726
DpcPreference bindDeviceAdminPreference =
724727
(DpcPreference) findPreference(BIND_DEVICE_ADMIN_POLICIES);
@@ -1287,6 +1290,9 @@ public void onPositiveButtonClicked(String[] lockTaskArray) {
12871290
case FACTORY_RESET_ORG_OWNED_DEVICE:
12881291
factoryResetOrgOwnedDevice();
12891292
return true;
1293+
case SET_FACTORY_RESET_PROTECTION_POLICY_KEY:
1294+
showFragment(new FactoryResetProtectionPolicyFragment());
1295+
return true;
12901296
}
12911297
return false;
12921298
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright (C) 2020 Google Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:layout_width="match_parent"
20+
android:layout_height="match_parent"
21+
android:orientation="vertical" >
22+
23+
<LinearLayout
24+
android:layout_width="match_parent"
25+
android:layout_height="0dp"
26+
android:orientation="vertical"
27+
android:paddingStart="8dp"
28+
android:paddingEnd="8dp"
29+
android:layout_weight="1" >
30+
31+
<TextView
32+
style="?android:attr/listSeparatorTextViewStyle"
33+
android:layout_width="match_parent"
34+
android:layout_height="wrap_content"
35+
android:paddingStart="8dp"
36+
android:paddingEnd="8dp"
37+
android:text="@string/factory_reset_protection_policy_accounts"
38+
android:textAlignment="viewStart"
39+
android:textColor="?android:attr/colorAccent"
40+
android:textSize="14sp" />
41+
42+
<ListView
43+
android:id="@+id/frp_accounts"
44+
android:layout_width="wrap_content"
45+
android:layout_height="wrap_content"
46+
android:paddingTop="4dp"/>
47+
48+
<Button
49+
android:id="@+id/add_account_button"
50+
android:layout_width="wrap_content"
51+
android:layout_height="wrap_content"
52+
android:layout_marginEnd="5dp"
53+
android:text="@string/add_account" />
54+
55+
<TextView
56+
android:layout_width="match_parent"
57+
android:layout_height="wrap_content"
58+
android:paddingStart="8dp"
59+
android:paddingEnd="8dp"
60+
android:textSize="14sp"
61+
android:textAlignment="viewStart"
62+
android:textColor="?android:attr/colorAccent"
63+
android:text="@string/factory_reset_protection_policy_enabled"
64+
style="?android:attr/listSeparatorTextViewStyle" />
65+
66+
<Spinner android:id="@+id/frp_enabled"
67+
android:layout_width="match_parent"
68+
android:layout_height="wrap_content" />
69+
</LinearLayout>
70+
71+
<LinearLayout
72+
android:layout_width="match_parent"
73+
android:layout_height="wrap_content"
74+
android:orientation="vertical"
75+
style="?android:attr/buttonBarStyle"
76+
android:divider="?android:attr/dividerHorizontal"
77+
android:showDividers="beginning">
78+
79+
<LinearLayout
80+
android:layout_width="match_parent"
81+
android:layout_height="wrap_content"
82+
android:orientation="horizontal"
83+
android:showDividers="middle">
84+
85+
<Button android:id="@+id/clear_frp_button"
86+
android:layout_width="0dp"
87+
android:layout_height="wrap_content"
88+
android:layout_weight="1"
89+
android:text="@string/clear"
90+
android:background="?android:attr/selectableItemBackground"
91+
style="?android:attr/buttonBarButtonStyle" />
92+
93+
<Button android:id="@+id/save_frp_button"
94+
android:layout_width="0dp"
95+
android:layout_height="wrap_content"
96+
android:layout_weight="1"
97+
android:text="@string/save"
98+
android:background="?android:attr/selectableItemBackground"
99+
style="?android:attr/buttonBarButtonStyle" />
100+
</LinearLayout>
101+
</LinearLayout>
102+
103+
</LinearLayout>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright (C) 2020 Google Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:layout_width="match_parent"
20+
android:layout_height="match_parent" >
21+
22+
<TextView
23+
android:id="@+id/frp_account"
24+
android:layout_width="wrap_content"
25+
android:layout_height="wrap_content"
26+
android:layout_centerVertical="true"
27+
android:layout_alignParentStart="true"
28+
android:paddingStart="8dp"
29+
android:textSize="16sp"
30+
android:textColor="?android:attr/colorPrimary"/>
31+
32+
<Button
33+
android:id="@+id/remove_account_button"
34+
android:layout_width="wrap_content"
35+
android:layout_height="wrap_content"
36+
android:layout_alignParentEnd="true"
37+
android:layout_centerVertical="true"
38+
android:layout_marginEnd="5dp"
39+
android:text="@string/delete_button_label" />
40+
41+
</RelativeLayout>

0 commit comments

Comments
 (0)