DO NOT MERGE - Revert workaround for KeyguardLock problem

This reverts commit 3ee0cad5f5.

Because commit 284b62e1b8c3419bfd02c6fea5ba0a68146c06f8 fixes the underlying
conflict between DeviceAdmin policies and apps attempting to disable the
Keyguard Lock, this patch is no longer required.

Accounts with a server policy requiring a device PIN or Password will
now work properly.

Bug: 2737842
Change-Id: I533c27a01a8a331dc11a0cb84bcc78f48edf621c
This commit is contained in:
Andrew Stadler 2010-06-11 11:21:41 -07:00
parent 8cfeacdcb3
commit 572c06f91b
7 changed files with 15 additions and 193 deletions

View File

@ -235,13 +235,6 @@
<intent-filter>
<action android:name="android.intent.action.DEVICE_STORAGE_OK" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_CHANGED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<!-- Support for DeviceAdmin / DevicePolicyManager. See SecurityPolicy class for impl. -->

View File

@ -681,12 +681,6 @@
<string name="device_admin_label">Email</string>
<!-- Long-form description of the DeviceAdmin (2nd line in settings & in user conf. screen) -->
<string name="device_admin_description">Enables server-specified security policies</string>
<!-- Title of keyguard-lock-disabled dialog box -->
<string name="keyguard_disabled_dlg_title">Screen lock disabled</string>
<!-- Message of keyguard-lock-disabled dialog box -->
<string name="keyguard_disabled_dlg_message_fmt">This account cannot be used while the
application \"<xliff:g id="application">%s</xliff:g>\" is installed, because it
interferes with the operation of the screen lock.</string>
<!-- Notification message in notifications window when calendar sync is
automatically enabled for pre-existing Exchange accounts on upgrade -->

View File

@ -250,12 +250,6 @@ public class Email extends Application {
*/
MailService.actionReschedule(context);
}
// If enabling, clear the cached test for keyguard-disabling apps; This is because
// we may have missed package install/replace/remove broadcasts while we had no accounts
// and the BootReceiver was disabled.
if (enabled) {
SecurityPolicy.getInstance(context.getApplicationContext()).invalidateKeyguardCache();
}
}
@Override

View File

@ -33,16 +33,11 @@ import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.util.Log;
import java.util.List;
/**
* Utility functions to support reading and writing security policies, and handshaking the device
* into and out of various security states.
@ -54,10 +49,6 @@ public class SecurityPolicy {
private DevicePolicyManager mDPM;
private ComponentName mAdminName;
private PolicySet mAggregatePolicy;
// false = unknown, true = mKeyguardDisablePackageName is valid (or null)
private boolean mKeyguardDisableChecked;
// null = no apps disabling, non-null = one or more apps disabling
private String mKeyguardDisablePackageName;
/* package */ static final PolicySet NO_POLICY_SET =
new PolicySet(0, PolicySet.PASSWORD_MODE_NONE, 0, 0, false);
@ -110,7 +101,6 @@ public class SecurityPolicy {
mDPM = null;
mAdminName = new ComponentName(context, PolicyAdmin.class);
mAggregatePolicy = null;
mKeyguardDisableChecked = false;
}
/**
@ -275,13 +265,6 @@ public class SecurityPolicy {
}
}
if (policies.mPasswordMode > 0) {
// If the server requests a password policy of any kind (PIN, password, etc)
// and the user has a keyguard-disable package, then we cannot support the
// policy. In a rare case of a server that doesn't enforce PIN/Password, we
// won't do this test.
if (getKeyguardDisablePackage() != null) {
return false;
}
if (dpm.getPasswordQuality(mAdminName) < policies.getDPManagerPasswordQuality()) {
return false;
}
@ -627,55 +610,6 @@ public class SecurityPolicy {
return dpm.isAdminActive(mAdminName);
}
/**
* Invalidate the cached result of checking for lock screen disablers. Called by package
* add/replace/delete broadcasts.
*/
public synchronized void invalidateKeyguardCache() {
mKeyguardDisableChecked = false;
mKeyguardDisablePackageName = null;
}
/**
* Return the name of any app that is disabling the keyguard (lock screen) - in which case,
* we must treat the device as if required lock screen policies are not met.
*
* @return non-null if any app is disabling the keyguard
*/
public synchronized String getKeyguardDisablePackage() {
if (!mKeyguardDisableChecked) {
mKeyguardDisablePackageName = findKeyguardPermission();
mKeyguardDisableChecked = true;
}
return mKeyguardDisablePackageName;
}
/**
* Scan installed packages and look for DISABLE_KEYGUARD permission. Return the first
* installed packages (if any are found). This won't be cheap, so do it as little as possible.
*
* @return the display name of the package, or null if all clear
*/
private String findKeyguardPermission() {
PackageManager pm = mContext.getPackageManager();
List<PackageInfo> packages = pm.getInstalledPackages(0);
for (PackageInfo info : packages) {
// skip over system packages; they are allowed to have the permission
if (0 != (info.applicationInfo.flags &
(ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP))) {
continue;
}
// all other packages, check for specific permission
int permissionResult = pm.checkPermission(android.Manifest.permission.DISABLE_KEYGUARD,
info.packageName);
if (permissionResult == PackageManager.PERMISSION_GRANTED) {
Log.d(Email.LOG_TAG, "DISABLE_KEYGUARD found in " + info.packageName);
return info.applicationInfo.loadLabel(pm).toString();
}
}
return null;
}
/**
* Report admin component name - for making calls into device policy manager
*/

View File

@ -21,11 +21,8 @@ import com.android.email.SecurityPolicy;
import com.android.email.provider.EmailContent.Account;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
@ -43,12 +40,8 @@ public class AccountSecurity extends Activity {
private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity.setup.ACCOUNT_ID";
private static final int DIALOG_KEYGUARD_DISABLED = 1;
private static final int REQUEST_ENABLE = 1;
private String mKeyguardBlockerName;
/**
* Used for generating intent for this activity (which is intended to be launched
* from a notification.)
@ -66,11 +59,6 @@ public class AccountSecurity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean finishNow = true;
// Return RESULT_OK in all cases unless explicitly changed (see below). This is ignored
// when we're launched from notification, but it's checked when we're launched from
// (and return to) AccountSetupNames.
setResult(Activity.RESULT_OK);
Intent i = getIntent();
long accountId = i.getLongExtra(EXTRA_ACCOUNT_ID, -1);
@ -80,8 +68,7 @@ public class AccountSecurity extends Activity {
// TODO: spin up a thread to do this in the background, because of DB ops
Account account = Account.restoreAccountWithId(this, accountId);
if (account != null) {
if ((account.mSecurityFlags != 0) ||
(0 != (account.mFlags & Account.FLAGS_SECURITY_HOLD))) {
if (account.mSecurityFlags != 0) {
// This account wants to control security
if (!security.isActiveAdmin()) {
// try to become active - must happen here in this activity, to get result
@ -96,14 +83,12 @@ public class AccountSecurity extends Activity {
return;
} else {
// already active - try to set actual policies, finish, and return
finishNow = setActivePolicies();
setActivePolicies();
}
}
}
}
if (finishNow) {
finish();
}
finish();
}
/**
@ -111,12 +96,11 @@ public class AccountSecurity extends Activity {
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
boolean finishNow = true;
switch (requestCode) {
case REQUEST_ENABLE:
if (resultCode == Activity.RESULT_OK) {
// now active - try to set actual policies
finishNow = setActivePolicies();
setActivePolicies();
} else {
// failed - repost notification, and exit
final long accountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1);
@ -131,85 +115,31 @@ public class AccountSecurity extends Activity {
}
}
}
// This activity has no layout and in most cases serves only as a dispatcher for
// checking and adjusting device security policies. However, in a few cases, it
// presents an error dialog. In those cases, setActivePolicies() will return false, and
// we don't call finish() so the dialog is able to display.
if (finishNow) {
finish();
}
finish();
super.onActivityResult(requestCode, resultCode, data);
}
/**
* Now that we are connected as an active device admin, try to set the device to the
* correct security level, and ask for a password if necessary.
*
* @return true if OK to finish the activity (false if we posted a dialog)
*/
private boolean setActivePolicies() {
private void setActivePolicies() {
SecurityPolicy sp = SecurityPolicy.getInstance(this);
// check current security level - if sufficient, we're done!
if (sp.isActive(null)) {
sp.clearAccountHoldFlags();
return true;
return;
}
// set current security level
sp.setActivePolicies();
// check current security level - if sufficient, we're done!
if (sp.isActive(null)) {
sp.clearAccountHoldFlags();
return true;
}
// if the problem is an app blocking the lock screen, notify the user
String keyguardBlocker = sp.getKeyguardDisablePackage();
if (keyguardBlocker != null) {
mKeyguardBlockerName = keyguardBlocker;
showDialog(DIALOG_KEYGUARD_DISABLED);
// Set activity to return RESULT_CANCELED (after dialog) to notify caller that we
// didn't configure policies completely.
setResult(Activity.RESULT_CANCELED);
return false;
return;
}
// if not sufficient, launch the activity to have the user set a new password.
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
startActivity(intent);
// TODO: use startActivityForResult, and when we see the result, recheck to see
// if the user actually entered a sufficient password. If not, repost the notification.
return true;
}
@Override
public Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_KEYGUARD_DISABLED:
return new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.keyguard_disabled_dlg_title)
.setMessage(getString(R.string.keyguard_disabled_dlg_message_fmt,
mKeyguardBlockerName))
.setNeutralButton(R.string.okay_action, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dismissDialog(DIALOG_KEYGUARD_DISABLED);
finish();
}
})
.setCancelable(false)
.create();
}
return super.onCreateDialog(id);
}
/**
* Update a cached dialog with current values (e.g. account name)
*/
@Override
public void onPrepareDialog(int id, Dialog dialog) {
switch (id) {
case DIALOG_KEYGUARD_DISABLED:
AlertDialog alert = (AlertDialog) dialog;
alert.setMessage(getString(R.string.keyguard_disabled_dlg_message_fmt,
mKeyguardBlockerName));
}
}
}

View File

@ -19,7 +19,6 @@ package com.android.email.activity.setup;
import com.android.email.AccountBackupRestore;
import com.android.email.R;
import com.android.email.Utility;
import com.android.email.activity.AccountFolderList;
import com.android.email.activity.Welcome;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
@ -147,25 +146,12 @@ public class AccountSetupNames extends Activity implements OnClickListener {
@Override
public void onBackPressed() {
onBackPressed(true); // OK to "proceed" to next step (the account has been created)
}
private void onBackPressed(boolean okToProceed) {
boolean easFlowMode = getIntent().getBooleanExtra(EXTRA_EAS_FLOW, false);
if (easFlowMode) {
AccountSetupBasics.actionAccountCreateFinishedEas(this);
} else {
if (mAccount != null) {
if (okToProceed) {
AccountSetupBasics.actionAccountCreateFinished(this, mAccount.mId);
} else {
// This is what we do if the account was created, but somebody called
// onBackPressed(false), indicating that the new account's inbox should not be
// entered. In this case, we'll just go back to the accounts list.
// We don't use the typical "Welcome" activity because if there is only one
// account, it will also try to visit the inbox of that account.
AccountFolderList.actionShowAccounts(this);
}
AccountSetupBasics.actionAccountCreateFinished(this, mAccount.mId);
} else {
// Safety check here; If mAccount is null (due to external issues or bugs)
// just rewind back to Welcome, which can handle any configuration of accounts
@ -263,15 +249,14 @@ public class AccountSetupNames extends Activity implements OnClickListener {
/**
* Handle the eventual result from the security update activity
*
* TODO: If the user doesn't update the security, don't go to the MessageList.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_SECURITY:
// If we get RESULT_CANCEL, we tell onBackPressed that there was an error,
// and it won't try to take us to the MessageList of the new account.
onBackPressed(resultCode == Activity.RESULT_OK);
break;
onBackPressed();
}
super.onActivityResult(requestCode, resultCode, data);
}

View File

@ -18,7 +18,6 @@ package com.android.email.service;
import com.android.email.AccountBackupRestore;
import com.android.email.Email;
import com.android.email.SecurityPolicy;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -30,24 +29,17 @@ public class BootReceiver extends BroadcastReceiver {
// Restore accounts, if it has not happened already
AccountBackupRestore.restoreAccountsIfNeeded(context);
String intentAction = intent.getAction();
if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
// Returns true if there are any accounts
if (Email.setServicesEnabled(context)) {
MailService.actionReschedule(context);
}
}
else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intentAction)) {
else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction())) {
MailService.actionCancel(context);
}
else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intentAction)) {
else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(intent.getAction())) {
MailService.actionReschedule(context);
}
else if (Intent.ACTION_PACKAGE_ADDED.equals(intentAction) ||
Intent.ACTION_PACKAGE_REPLACED.equals(intentAction) ||
Intent.ACTION_PACKAGE_REMOVED.equals(intentAction)) {
SecurityPolicy.getInstance(context.getApplicationContext()).invalidateKeyguardCache();
}
}
}