Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2010 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.android.apis.app;
     18 
     19 import com.example.android.apis.R;
     20 
     21 import android.app.Activity;
     22 import android.app.ActivityManager;
     23 import android.app.AlertDialog;
     24 import android.app.admin.DeviceAdminReceiver;
     25 import android.app.admin.DevicePolicyManager;
     26 import android.content.ComponentName;
     27 import android.content.Context;
     28 import android.content.DialogInterface;
     29 import android.content.Intent;
     30 import android.content.SharedPreferences;
     31 import android.os.Bundle;
     32 import android.text.Editable;
     33 import android.text.TextWatcher;
     34 import android.util.Log;
     35 import android.view.View;
     36 import android.view.View.OnClickListener;
     37 import android.widget.AdapterView;
     38 import android.widget.ArrayAdapter;
     39 import android.widget.Button;
     40 import android.widget.EditText;
     41 import android.widget.Spinner;
     42 import android.widget.Toast;
     43 import android.widget.AdapterView.OnItemSelectedListener;
     44 
     45 /**
     46  * Example of a do-nothing admin class.  When enabled, it lets you control
     47  * some of its policy and reports when there is interesting activity.
     48  */
     49 public class DeviceAdminSample extends DeviceAdminReceiver {
     50 
     51     static SharedPreferences getSamplePreferences(Context context) {
     52         return context.getSharedPreferences(DeviceAdminReceiver.class.getName(), 0);
     53     }
     54 
     55     static String PREF_PASSWORD_QUALITY = "password_quality";
     56     static String PREF_PASSWORD_LENGTH = "password_length";
     57     static String PREF_MAX_FAILED_PW = "max_failed_pw";
     58 
     59     void showToast(Context context, CharSequence msg) {
     60         Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
     61     }
     62 
     63     @Override
     64     public void onEnabled(Context context, Intent intent) {
     65         showToast(context, "Sample Device Admin: enabled");
     66     }
     67 
     68     @Override
     69     public CharSequence onDisableRequested(Context context, Intent intent) {
     70         return "This is an optional message to warn the user about disabling.";
     71     }
     72 
     73     @Override
     74     public void onDisabled(Context context, Intent intent) {
     75         showToast(context, "Sample Device Admin: disabled");
     76     }
     77 
     78     @Override
     79     public void onPasswordChanged(Context context, Intent intent) {
     80         showToast(context, "Sample Device Admin: pw changed");
     81     }
     82 
     83     @Override
     84     public void onPasswordFailed(Context context, Intent intent) {
     85         showToast(context, "Sample Device Admin: pw failed");
     86     }
     87 
     88     @Override
     89     public void onPasswordSucceeded(Context context, Intent intent) {
     90         showToast(context, "Sample Device Admin: pw succeeded");
     91     }
     92 
     93     /**
     94      * <p>UI control for the sample device admin.  This provides an interface
     95      * to enable, disable, and perform other operations with it to see
     96      * their effect.</p>
     97      *
     98      * <p>Note that this is implemented as an inner class only keep the sample
     99      * all together; typically this code would appear in some separate class.
    100      */
    101     public static class Controller extends Activity {
    102         static final int RESULT_ENABLE = 1;
    103 
    104         DevicePolicyManager mDPM;
    105         ActivityManager mAM;
    106         ComponentName mDeviceAdminSample;
    107 
    108         Button mEnableButton;
    109         Button mDisableButton;
    110 
    111         // Password quality spinner choices
    112         // This list must match the list found in samples/ApiDemos/res/values/arrays.xml
    113         final static int mPasswordQualityValues[] = new int[] {
    114             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    115             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
    116             DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
    117             DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
    118             DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
    119         };
    120         Spinner mPasswordQuality;
    121         EditText mPasswordLength;
    122         Button mSetPasswordButton;
    123 
    124         EditText mPassword;
    125         Button mResetPasswordButton;
    126 
    127         EditText mMaxFailedPw;
    128 
    129         Button mForceLockButton;
    130         Button mWipeDataButton;
    131 
    132         private Button mTimeoutButton;
    133 
    134         private EditText mTimeout;
    135 
    136         @Override
    137         protected void onCreate(Bundle savedInstanceState) {
    138             super.onCreate(savedInstanceState);
    139 
    140             mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
    141             mAM = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
    142             mDeviceAdminSample = new ComponentName(Controller.this, DeviceAdminSample.class);
    143 
    144             setContentView(R.layout.device_admin_sample);
    145 
    146             // Watch for button clicks.
    147             mEnableButton = (Button)findViewById(R.id.enable);
    148             mEnableButton.setOnClickListener(mEnableListener);
    149             mDisableButton = (Button)findViewById(R.id.disable);
    150             mDisableButton.setOnClickListener(mDisableListener);
    151 
    152             mPasswordQuality = (Spinner)findViewById(R.id.password_quality);
    153             ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
    154                     this, R.array.password_qualities, android.R.layout.simple_spinner_item);
    155             adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    156             mPasswordQuality.setAdapter(adapter);
    157             mPasswordQuality.setOnItemSelectedListener(
    158                     new OnItemSelectedListener() {
    159                         public void onItemSelected(
    160                                 AdapterView<?> parent, View view, int position, long id) {
    161                             setPasswordQuality(mPasswordQualityValues[position]);
    162                         }
    163 
    164                         public void onNothingSelected(AdapterView<?> parent) {
    165                             setPasswordQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
    166                         }
    167                     });
    168             mPasswordLength = (EditText)findViewById(R.id.password_length);
    169             mPasswordLength.addTextChangedListener(new TextWatcher() {
    170                 public void afterTextChanged(Editable s) {
    171                 }
    172                 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    173                 }
    174                 public void onTextChanged(CharSequence s, int start, int before, int count) {
    175                     try {
    176                         setPasswordLength(Integer.parseInt(s.toString()));
    177                     } catch (NumberFormatException e) {
    178                     }
    179                 }
    180             });
    181             mSetPasswordButton = (Button)findViewById(R.id.set_password);
    182             mSetPasswordButton.setOnClickListener(mSetPasswordListener);
    183 
    184             mPassword = (EditText)findViewById(R.id.password);
    185             mResetPasswordButton = (Button)findViewById(R.id.reset_password);
    186             mResetPasswordButton.setOnClickListener(mResetPasswordListener);
    187 
    188             mMaxFailedPw = (EditText)findViewById(R.id.max_failed_pw);
    189             mMaxFailedPw.addTextChangedListener(new TextWatcher() {
    190                 public void afterTextChanged(Editable s) {
    191                 }
    192                 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    193                 }
    194                 public void onTextChanged(CharSequence s, int start, int before, int count) {
    195                     try {
    196                         int maxFailCount = Integer.parseInt(s.toString());
    197                         if (maxFailCount > 0) {
    198                             Toast.makeText(Controller.this, "WARNING: Phone will wipe after " +
    199                                     s + " incorrect passwords", Toast.LENGTH_SHORT).show();
    200                         }
    201                         setMaxFailedPw(maxFailCount);
    202                     } catch (NumberFormatException e) {
    203                     }
    204                 }
    205             });
    206 
    207             mForceLockButton = (Button)findViewById(R.id.force_lock);
    208             mForceLockButton.setOnClickListener(mForceLockListener);
    209             mWipeDataButton = (Button)findViewById(R.id.wipe_data);
    210             mWipeDataButton.setOnClickListener(mWipeDataListener);
    211 
    212             mTimeout = (EditText) findViewById(R.id.timeout);
    213             mTimeoutButton = (Button) findViewById(R.id.set_timeout);
    214             mTimeoutButton.setOnClickListener(mSetTimeoutListener);
    215         }
    216 
    217         void updateButtonStates() {
    218             boolean active = mDPM.isAdminActive(mDeviceAdminSample);
    219             if (active) {
    220                 mEnableButton.setEnabled(false);
    221                 mDisableButton.setEnabled(true);
    222                 mPasswordQuality.setEnabled(true);
    223                 mPasswordLength.setEnabled(true);
    224                 mSetPasswordButton.setEnabled(true);
    225                 mPassword.setEnabled(true);
    226                 mResetPasswordButton.setEnabled(true);
    227                 mForceLockButton.setEnabled(true);
    228                 mWipeDataButton.setEnabled(true);
    229             } else {
    230                 mEnableButton.setEnabled(true);
    231                 mDisableButton.setEnabled(false);
    232                 mPasswordQuality.setEnabled(false);
    233                 mPasswordLength.setEnabled(false);
    234                 mSetPasswordButton.setEnabled(false);
    235                 mPassword.setEnabled(false);
    236                 mResetPasswordButton.setEnabled(false);
    237                 mForceLockButton.setEnabled(false);
    238                 mWipeDataButton.setEnabled(false);
    239             }
    240         }
    241 
    242         void updateControls() {
    243             SharedPreferences prefs = getSamplePreferences(this);
    244             final int pwQuality = prefs.getInt(PREF_PASSWORD_QUALITY,
    245                     DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
    246             final int pwLength = prefs.getInt(PREF_PASSWORD_LENGTH, 0);
    247             final int maxFailedPw = prefs.getInt(PREF_MAX_FAILED_PW, 0);
    248 
    249             for (int i=0; i<mPasswordQualityValues.length; i++) {
    250                 if (mPasswordQualityValues[i] == pwQuality) {
    251                     mPasswordQuality.setSelection(i);
    252                 }
    253             }
    254             mPasswordLength.setText(Integer.toString(pwLength));
    255             mMaxFailedPw.setText(Integer.toString(maxFailedPw));
    256         }
    257 
    258         void updatePolicies() {
    259             SharedPreferences prefs = getSamplePreferences(this);
    260             final int pwQuality = prefs.getInt(PREF_PASSWORD_QUALITY,
    261                     DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
    262             final int pwLength = prefs.getInt(PREF_PASSWORD_LENGTH, 0);
    263             final int maxFailedPw = prefs.getInt(PREF_MAX_FAILED_PW, 0);
    264 
    265             boolean active = mDPM.isAdminActive(mDeviceAdminSample);
    266             if (active) {
    267                 mDPM.setPasswordQuality(mDeviceAdminSample, pwQuality);
    268                 mDPM.setPasswordMinimumLength(mDeviceAdminSample, pwLength);
    269                 mDPM.setMaximumFailedPasswordsForWipe(mDeviceAdminSample, maxFailedPw);
    270             }
    271         }
    272 
    273         void setPasswordQuality(int quality) {
    274             SharedPreferences prefs = getSamplePreferences(this);
    275             prefs.edit().putInt(PREF_PASSWORD_QUALITY, quality).commit();
    276             updatePolicies();
    277         }
    278 
    279         void setPasswordLength(int length) {
    280             SharedPreferences prefs = getSamplePreferences(this);
    281             prefs.edit().putInt(PREF_PASSWORD_LENGTH, length).commit();
    282             updatePolicies();
    283         }
    284 
    285         void setMaxFailedPw(int length) {
    286             SharedPreferences prefs = getSamplePreferences(this);
    287             prefs.edit().putInt(PREF_MAX_FAILED_PW, length).commit();
    288             updatePolicies();
    289         }
    290 
    291         @Override
    292         protected void onResume() {
    293             super.onResume();
    294             updateButtonStates();
    295         }
    296 
    297         @Override
    298         protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    299             switch (requestCode) {
    300                 case RESULT_ENABLE:
    301                     if (resultCode == Activity.RESULT_OK) {
    302                         Log.i("DeviceAdminSample", "Admin enabled!");
    303                     } else {
    304                         Log.i("DeviceAdminSample", "Admin enable FAILED!");
    305                     }
    306                     return;
    307             }
    308 
    309             super.onActivityResult(requestCode, resultCode, data);
    310         }
    311 
    312         private OnClickListener mEnableListener = new OnClickListener() {
    313             public void onClick(View v) {
    314                 // Launch the activity to have the user enable our admin.
    315                 Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    316                 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
    317                         mDeviceAdminSample);
    318                 intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
    319                         "Additional text explaining why this needs to be added.");
    320                 startActivityForResult(intent, RESULT_ENABLE);
    321             }
    322         };
    323 
    324         private OnClickListener mDisableListener = new OnClickListener() {
    325             public void onClick(View v) {
    326                 mDPM.removeActiveAdmin(mDeviceAdminSample);
    327                 updateButtonStates();
    328             }
    329         };
    330 
    331         private OnClickListener mSetPasswordListener = new OnClickListener() {
    332             public void onClick(View v) {
    333                 // Launch the activity to have the user set a new password.
    334                 Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    335                 startActivity(intent);
    336             }
    337         };
    338 
    339         private OnClickListener mResetPasswordListener = new OnClickListener() {
    340             public void onClick(View v) {
    341                 if (mAM.isUserAMonkey()) {
    342                     // Don't trust monkeys to do the right thing!
    343                     AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
    344                     builder.setMessage("You can't reset my password because you are a monkey!");
    345                     builder.setPositiveButton("I admit defeat", null);
    346                     builder.show();
    347                     return;
    348                 }
    349                 boolean active = mDPM.isAdminActive(mDeviceAdminSample);
    350                 if (active) {
    351                     mDPM.resetPassword(mPassword.getText().toString(),
    352                             DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
    353                 }
    354             }
    355         };
    356 
    357         private OnClickListener mForceLockListener = new OnClickListener() {
    358             public void onClick(View v) {
    359                 if (mAM.isUserAMonkey()) {
    360                     // Don't trust monkeys to do the right thing!
    361                     AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
    362                     builder.setMessage("You can't lock my screen because you are a monkey!");
    363                     builder.setPositiveButton("I admit defeat", null);
    364                     builder.show();
    365                     return;
    366                 }
    367                 boolean active = mDPM.isAdminActive(mDeviceAdminSample);
    368                 if (active) {
    369                     mDPM.lockNow();
    370                 }
    371             }
    372         };
    373 
    374         private OnClickListener mWipeDataListener = new OnClickListener() {
    375             public void onClick(View v) {
    376                 if (mAM.isUserAMonkey()) {
    377                     // Don't trust monkeys to do the right thing!
    378                     AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
    379                     builder.setMessage("You can't wipe my data because you are a monkey!");
    380                     builder.setPositiveButton("I admit defeat", null);
    381                     builder.show();
    382                     return;
    383                 }
    384                 AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
    385                 builder.setMessage("This will erase all of your data.  Are you sure?");
    386                 builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    387                     public void onClick(DialogInterface dialog, int which) {
    388                         AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
    389                         builder.setMessage("This is not a test.  "
    390                                 + "This WILL erase all of your data!  "
    391                                 + "Are you really absolutely sure?");
    392                         builder.setPositiveButton("BOOM!", new DialogInterface.OnClickListener() {
    393                             public void onClick(DialogInterface dialog, int which) {
    394                                 boolean active = mDPM.isAdminActive(mDeviceAdminSample);
    395                                 if (active) {
    396                                     mDPM.wipeData(0);
    397                                 }
    398                             }
    399                         });
    400                         builder.setNegativeButton("Oops, run away!", null);
    401                         builder.show();
    402                     }
    403                 });
    404                 builder.setNegativeButton("No way!", null);
    405                 builder.show();
    406             }
    407         };
    408 
    409         private OnClickListener mSetTimeoutListener = new OnClickListener() {
    410 
    411             public void onClick(View v) {
    412                 if (mAM.isUserAMonkey()) {
    413                     // Don't trust monkeys to do the right thing!
    414                     AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
    415                     builder.setMessage("You can't lock my screen because you are a monkey!");
    416                     builder.setPositiveButton("I admit defeat", null);
    417                     builder.show();
    418                     return;
    419                 }
    420                 boolean active = mDPM.isAdminActive(mDeviceAdminSample);
    421                 if (active) {
    422                     long timeMs = 1000L*Long.parseLong(mTimeout.getText().toString());
    423                     mDPM.setMaximumTimeToLock(mDeviceAdminSample, timeMs);
    424                 }
    425             }
    426         };
    427     }
    428 }
    429