AccountSecurity.java revision 469f2987dc11d153434e50eb04dd6b83b924d09d
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 17package com.android.email.activity.setup; 18 19import com.android.email.R; 20import com.android.email.SecurityPolicy; 21import com.android.email.activity.ActivityHelper; 22import com.android.email.provider.EmailContent.Account; 23import com.android.email.provider.EmailContent.HostAuth; 24 25import android.app.Activity; 26import android.app.admin.DevicePolicyManager; 27import android.content.Context; 28import android.content.Intent; 29import android.os.Bundle; 30 31/** 32 * Psuedo-activity (no UI) to bootstrap the user up to a higher desired security level. This 33 * bootstrap requires the following steps. 34 * 35 * 1. Confirm the account of interest has any security policies defined - exit early if not 36 * 2. If not actively administrating the device, ask Device Policy Manager to start that 37 * 3. When we are actively administrating, check current policies and see if they're sufficient 38 * 4. If not, set policies 39 * 5. If necessary, request for user to update device password 40 * 6. If necessary, request for user to activate device encryption 41 */ 42public class AccountSecurity extends Activity { 43 44 private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity.setup.ACCOUNT_ID"; 45 46 private static final int REQUEST_ENABLE = 1; 47 private static final int REQUEST_PASSWORD = 2; 48 private static final int REQUEST_ENCRYPTION = 3; 49 50 /** 51 * Used for generating intent for this activity (which is intended to be launched 52 * from a notification.) 53 * 54 * @param context Calling context for building the intent 55 * @param accountId The account of interest 56 * @return an Intent which can be used to view that account 57 */ 58 public static Intent actionUpdateSecurityIntent(Context context, long accountId) { 59 Intent intent = new Intent(context, AccountSecurity.class); 60 intent.putExtra(EXTRA_ACCOUNT_ID, accountId); 61 return intent; 62 } 63 64 @Override 65 public void onCreate(Bundle savedInstanceState) { 66 super.onCreate(savedInstanceState); 67 ActivityHelper.debugSetWindowFlags(this); 68 69 Intent i = getIntent(); 70 long accountId = i.getLongExtra(EXTRA_ACCOUNT_ID, -1); 71 SecurityPolicy security = SecurityPolicy.getInstance(this); 72 security.clearNotification(accountId); 73 if (accountId != -1) { 74 // TODO: spin up a thread to do this in the background, because of DB ops 75 Account account = Account.restoreAccountWithId(this, accountId); 76 if (account != null) { 77 if (account.mSecurityFlags != 0) { 78 // This account wants to control security 79 if (!security.isActiveAdmin()) { 80 // retrieve name of server for the format string 81 HostAuth hostAuth = 82 HostAuth.restoreHostAuthWithId(this, account.mHostAuthKeyRecv); 83 if (hostAuth != null) { 84 // try to become active - must happen here in activity, to get result 85 Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); 86 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, 87 security.getAdminComponent()); 88 intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, 89 this.getString(R.string.account_security_policy_explanation_fmt, 90 hostAuth.mAddress)); 91 startActivityForResult(intent, REQUEST_ENABLE); 92 // keep this activity on stack to process result 93 return; 94 } 95 } else { 96 // already active - try to set actual policies, finish, and return 97 boolean startedActivity = setActivePolicies(); 98 if (startedActivity) { 99 // keep this activity on stack to process result 100 return; 101 } 102 } 103 } 104 } 105 } 106 finish(); 107 } 108 109 /** 110 * Handle the eventual result of the user allowing us to become an active device admin 111 */ 112 @Override 113 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 114 boolean startedActivity = false; 115 switch (requestCode) { 116 case REQUEST_PASSWORD: 117 case REQUEST_ENCRYPTION: 118 // Force the result code and just check the DPM to check for actual success 119 resultCode = Activity.RESULT_OK; 120 //$FALL-THROUGH$ 121 case REQUEST_ENABLE: 122 if (resultCode == Activity.RESULT_OK) { 123 // now active - try to set actual policies 124 startedActivity = setActivePolicies(); 125 } else { 126 // failed - repost notification, and exit 127 final long accountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1); 128 if (accountId != -1) { 129 new Thread() { 130 @Override 131 public void run() { 132 SecurityPolicy.getInstance(AccountSecurity.this) 133 .policiesRequired(accountId); 134 } 135 }.start(); 136 } 137 } 138 } 139 if (!startedActivity) { 140 finish(); 141 } 142 super.onActivityResult(requestCode, resultCode, data); 143 } 144 145 /** 146 * Now that we are connected as an active device admin, try to set the device to the 147 * correct security level, and ask for a password if necessary. 148 * @return true if we started another activity (and should not finish(), as we're waiting for 149 * their result.) 150 */ 151 private boolean setActivePolicies() { 152 SecurityPolicy sp = SecurityPolicy.getInstance(this); 153 // check current security level - if sufficient, we're done! 154 if (sp.isActive(null)) { 155 Account.clearSecurityHoldOnAllAccounts(this); 156 return false; 157 } 158 // set current security level 159 sp.setActivePolicies(); 160 // check current security level - if sufficient, we're done! 161 int inactiveReasons = sp.getInactiveReasons(null); 162 if (inactiveReasons == 0) { 163 Account.clearSecurityHoldOnAllAccounts(this); 164 return false; 165 } 166 // If password or encryption required, launch relevant intent 167 if ((inactiveReasons & SecurityPolicy.INACTIVE_NEED_PASSWORD) != 0) { 168 // launch the activity to have the user set a new password. 169 Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD); 170 startActivityForResult(intent, REQUEST_PASSWORD); 171 return true; 172 } else if ((inactiveReasons & SecurityPolicy.INACTIVE_NEED_ENCRYPTION) != 0) { 173 // launch the activity to start up encryption. 174 Intent intent = new Intent(DevicePolicyManager.ACTION_START_ENCRYPTION); 175 startActivityForResult(intent, REQUEST_ENCRYPTION); 176 return true; 177 } 178 return false; 179 } 180} 181