1 /*
2  * Copyright (C) 2011 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.example.training.deviceadmin;
18 
19 import android.app.Activity;
20 import android.app.admin.DevicePolicyManager;
21 import android.content.Intent;
22 import android.content.SharedPreferences;
23 import android.os.Bundle;
24 import android.view.View;
25 import android.widget.AdapterView;
26 import android.widget.ArrayAdapter;
27 import android.widget.Button;
28 import android.widget.EditText;
29 import android.widget.LinearLayout;
30 import android.widget.Spinner;
31 import android.widget.TextView;
32 
33 /**
34  * Main Activity for the sample application.
35  *
36  * The Activity maintains and presents 2 different
37  * screens to the user -- a screen for configuring device administration policy and another screen
38  * for viewing configured policy.  When it is detected that the screen-lock password satisfies
39  * the password strength required by the policy, the user is sent to an Activity containing
40  * protected content.
41  */
42 public class PolicySetupActivity extends Activity {
43     private static final int REQ_ACTIVATE_DEVICE_ADMIN = 10;
44     private static final String SCREEN_ID_KEY = "LAYOUT_ID";
45 
46     private static final String APP_PREF = "APP_PREF";
47     private static final int UNKNOWN_SCREEN_ID = -1;
48 
49     // UI controls in policy setup screen.
50     private Spinner mPasswordQualityInputField;
51     private EditText mPasswordLengthInputField;
52     private EditText mPasswordMinUppercaseInputField;
53 
54     private Policy mPolicy;
55     private int mCurrentScreenId;
56 
57     @Override
onCreate(Bundle savedInstanceState)58     public void onCreate(Bundle savedInstanceState) {
59         super.onCreate(savedInstanceState);
60         mPolicy = new Policy(this);
61     }
62 
63     @Override
onResume()64     protected void onResume() {
65         super.onResume();
66 
67         SharedPreferences prefs = getSharedPreferences(APP_PREF, MODE_PRIVATE);
68         final int savedScreenId = prefs.getInt(SCREEN_ID_KEY, UNKNOWN_SCREEN_ID);
69         if (savedScreenId == UNKNOWN_SCREEN_ID || !mPolicy.isAdminActive()) {
70             setScreenContent(R.layout.activity_policy_setup);
71         } else {
72             setScreenContent(savedScreenId);
73         }
74     }
75 
setScreenContent(final int screenId)76     private void setScreenContent(final int screenId) {
77         mCurrentScreenId = screenId;
78         setContentView(mCurrentScreenId);
79         getSharedPreferences(APP_PREF, MODE_PRIVATE).edit().putInt(
80                 SCREEN_ID_KEY, mCurrentScreenId).commit();
81         switch (mCurrentScreenId) {
82         case R.layout.activity_policy_setup:
83             initPolicySetupScreen();
84             initNavigation();
85             break;
86         case R.layout.activity_view_policy:
87             initViewPolicyScreen();
88             initNavigation();
89             break;
90         }
91     }
92 
93     @Override
onPause()94     protected void onPause() {
95         super.onPause();
96         if (mCurrentScreenId == R.layout.activity_policy_setup) writePolicy();
97     }
98 
99     @Override
onActivityResult(int requestCode, int resultCode, Intent data)100     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
101         if (requestCode == REQ_ACTIVATE_DEVICE_ADMIN && resultCode == RESULT_OK) {
102             // User just activated the application as a device administrator.
103             setScreenContent(mCurrentScreenId);
104         } else {
105             super.onActivityResult(requestCode, resultCode, data);
106         }
107     }
108 
109     @Override
onBackPressed()110     public void onBackPressed() {
111         if (mCurrentScreenId == R.layout.activity_view_policy) {
112             setScreenContent(R.layout.activity_policy_setup);
113             return;
114         }
115         super.onBackPressed();
116     }
117 
118     // Initialize policy set up screen.
initPolicySetupScreen()119     private void initPolicySetupScreen() {
120         mPasswordQualityInputField = (Spinner) findViewById(R.id.policy_password_quality);
121         mPasswordLengthInputField = (EditText) findViewById(R.id.policy_password_length);
122         mPasswordMinUppercaseInputField = (EditText) findViewById(R.id.policy_password_uppercase);
123         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
124                 R.array.password_types, android.R.layout.simple_spinner_item);
125         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
126         mPasswordQualityInputField.setAdapter(adapter);
127         mPasswordQualityInputField.setOnItemSelectedListener(
128                 new AdapterView.OnItemSelectedListener() {
129             public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
130                 LinearLayout passwordMinUppercaseView =
131                         (LinearLayout) findViewById(R.id.password_uppercase_view);
132                 // The minimum number of upper case field is only applicable for password
133                 // qualities: alpha, alphanumeric, or complex.
134                 if (pos > 2)
135                     passwordMinUppercaseView.setVisibility(View.VISIBLE);
136                 else
137                     passwordMinUppercaseView.setVisibility(View.GONE);
138             }
139 
140             public void onNothingSelected(AdapterView<?> parent) {}
141         });
142 
143         // Read previously saved policy and populate on the UI.
144         mPolicy.readFromLocal();
145         mPasswordQualityInputField.setSelection(mPolicy.getPasswordQuality());
146         if (mPolicy.getPasswordLength() > 0) {
147             mPasswordLengthInputField.setText(String.valueOf(mPolicy.getPasswordLength()));
148         } else {
149             mPasswordLengthInputField.setText("");
150         }
151 
152         if (mPolicy.getPasswordMinUpperCase() > 0) {
153             mPasswordMinUppercaseInputField.setText(
154                     String.valueOf(mPolicy.getPasswordMinUpperCase()));
155         } else {
156             mPasswordMinUppercaseInputField.setText("");
157         }
158     }
159 
160     // Initialize policy viewing screen.
initViewPolicyScreen()161     private void initViewPolicyScreen() {
162         TextView passwordQualityView = (TextView) findViewById(R.id.policy_password_quality);
163         TextView passwordLengthView = (TextView) findViewById(R.id.policy_password_length);
164 
165         // Read previously saved policy and populate on the UI.
166         mPolicy.readFromLocal();
167         int passwordQualitySelection = mPolicy.getPasswordQuality();
168         passwordQualityView.setText(
169                 getResources().getStringArray(R.array.password_types)[passwordQualitySelection]);
170         passwordLengthView.setText(String.valueOf(mPolicy.getPasswordLength()));
171         if (passwordQualitySelection > 2) {
172             LinearLayout passwordMinUppercaseView =
173                     (LinearLayout) findViewById(R.id.password_uppercase_view);
174             passwordMinUppercaseView.setVisibility(View.VISIBLE);
175             ((TextView) findViewById(R.id.policy_password_uppercase)).setText(
176                     String.valueOf(mPolicy.getPasswordMinUpperCase()));
177         }
178     }
179 
180     // Set up navigation message and action button.
initNavigation()181     private void initNavigation() {
182         if (!mPolicy.isAdminActive()) {
183             // Activates device administrator.
184             setupNavigation(R.string.setup_message_activate,
185                     R.string.setup_action_activate,
186                     mActivateButtonListener);
187         } else if (mCurrentScreenId == R.layout.activity_policy_setup) {
188             setupNavigation(R.string.setup_message_set_policy,
189                     R.string.setup_action_set_policy,
190                     new View.OnClickListener() {
191                         public void onClick(View view) {
192                             writePolicy();
193                             mPolicy.configurePolicy();
194                             setScreenContent(R.layout.activity_view_policy);
195                         }
196                     });
197         }
198         else if (!mPolicy.isActivePasswordSufficient()) {
199             // Launches password set-up screen in Settings.
200             setupNavigation(R.string.setup_message_enforce_policy,
201                     R.string.setup_action_enforce_policy,
202                     mEnforcePolicyListener);
203         } else {
204             // Grants access to secure content.
205             setupNavigation(R.string.setup_message_go_secured,
206                     R.string.setup_action_go_secured,
207                     new View.OnClickListener() {
208                         public void onClick(View view) {
209                             startActivity(new Intent(view.getContext(), SecureActivity.class));
210                         }
211                     });
212         }
213     }
214 
215     private View.OnClickListener mActivateButtonListener = new View.OnClickListener() {
216         @Override
217         public void onClick(View v) {
218             // First, persist the policy.  Then, launch intent to trigger the system screen
219             // requesting user to confirm the activation of the device administrator.
220             writePolicy();
221             Intent activateDeviceAdminIntent =
222                 new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
223             activateDeviceAdminIntent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
224                     mPolicy.getPolicyAdmin());
225             // It is good practice to include the optional explanation text to explain to
226             // user why the application is requesting to be a device administrator.  The system
227             // will display this message on the activation screen.
228             activateDeviceAdminIntent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
229                     getResources().getString(R.string.device_admin_activation_message));
230             startActivityForResult(activateDeviceAdminIntent, REQ_ACTIVATE_DEVICE_ADMIN);
231         }
232     };
233 
234     private View.OnClickListener mEnforcePolicyListener = new View.OnClickListener() {
235         @Override
236         public void onClick(View v) {
237             writePolicy();
238             // The device administration API does not "fix" the password if it is
239             // determined that the current password does not conform to what is requested
240             // by the policy.  The caller is responsible for triggering the password set up
241             // screen via the below intent.
242             Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
243             startActivity(intent);
244         }
245     };
246 
247     // Setup action button text and listener.
setupNavigation(int messageResId, int buttonTextResId, View.OnClickListener listener)248     private void setupNavigation(int messageResId, int buttonTextResId,
249             View.OnClickListener listener) {
250         TextView setupMessage = (TextView) findViewById(R.id.setup_message);
251         setupMessage.setText(messageResId);
252         Button actionBtn = (Button) findViewById(R.id.setup_action_btn);
253         actionBtn.setText(buttonTextResId);
254         actionBtn.setOnClickListener(listener);
255     }
256 
257     // Save policy to shared preferences.
writePolicy()258     private void writePolicy() {
259         int passwordQuality = (int) mPasswordQualityInputField.getSelectedItemId();
260 
261         int passwordLength = 0;
262         try {
263             passwordLength = Integer.parseInt(mPasswordLengthInputField.getText().toString());
264         } catch (NumberFormatException nfe) {}  // Defaults to 0.
265 
266         int passwordMinUppercase = 0;
267         try {
268             passwordMinUppercase =
269                     Integer.parseInt(mPasswordMinUppercaseInputField.getText().toString());
270         } catch (NumberFormatException nfe) {}  // Defaults to 0.
271 
272         mPolicy.saveToLocal(passwordQuality, passwordLength, passwordMinUppercase);
273     }
274 }
275 
276