Prevent NPE's in AccountSecurity

* This CL fixes the referenced bug, but it does NOT explain how
  mAccount; best guess is that the process was killed and then
  restarted when the result from DPM was available.
* Assuming this is the case, we remove the background task loading
  mAccount, avoiding a possible race.
* Also, it's not clear why clearNotifications didn't use the
  account id argument; what if there's more than one account that
  uses security?  Filing a bug about this.

Bug: 5048912
Change-Id: I734834337ab6e409d77624e7c7370350de76becb
This commit is contained in:
Marc Blank 2011-07-19 14:09:11 -07:00
parent d1f03736e6
commit c6df1d605f
2 changed files with 46 additions and 58 deletions

View File

@ -16,16 +16,6 @@
package com.android.email;
import com.android.email.service.EmailBroadcastProcessorService;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.PolicyColumns;
import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.utility.Utility;
import com.google.common.annotations.VisibleForTesting;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
@ -37,6 +27,16 @@ import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import com.android.email.service.EmailBroadcastProcessorService;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.PolicyColumns;
import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.utility.Utility;
import com.google.common.annotations.VisibleForTesting;
/**
* Utility functions to support reading and writing security policies, and handshaking the device
* into and out of various security states.
@ -534,7 +534,7 @@ public class SecurityPolicy {
* Called from the notification's intent receiver to register that the notification can be
* cleared now.
*/
public void clearNotification(long accountId) {
public void clearNotification() {
NotificationController.getInstance(mContext).cancelSecurityNeededNotification();
}

View File

@ -26,7 +26,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
@ -109,58 +108,46 @@ public class AccountSecurity extends Activity {
final boolean passwordExpiring = i.getBooleanExtra(EXTRA_PASSWORD_EXPIRING, false);
final boolean passwordExpired = i.getBooleanExtra(EXTRA_PASSWORD_EXPIRED, false);
SecurityPolicy security = SecurityPolicy.getInstance(this);
security.clearNotification(accountId);
security.clearNotification();
if (accountId == -1) {
finish();
return;
}
// Let onCreate exit, while background thread retrieves account.
// Then start the security check/bootstrap process.
new AsyncTask<Void, Void, Account>() {
@Override
protected Account doInBackground(Void... params) {
return Account.restoreAccountWithId(AccountSecurity.this, accountId);
mAccount = Account.restoreAccountWithId(AccountSecurity.this, accountId);
if (mAccount == null) {
finish();
return;
}
// Special handling for password expiration events
if (passwordExpiring || passwordExpired) {
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag("password_expiration") == null) {
PasswordExpirationDialog dialog =
PasswordExpirationDialog.newInstance(mAccount.getDisplayName(),
passwordExpired);
dialog.show(fm, "password_expiration");
}
@Override
protected void onPostExecute(Account result) {
mAccount = result;
if (mAccount == null) {
finish();
return;
return;
}
// Otherwise, handle normal security settings flow
if (mAccount.mPolicyKey != 0) {
// This account wants to control security
if (showDialog) {
// Show dialog first, unless already showing (e.g. after rotation)
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag("security_needed") == null) {
SecurityNeededDialog dialog =
SecurityNeededDialog.newInstance(mAccount.getDisplayName());
dialog.show(fm, "security_needed");
}
// Special handling for password expiration events
if (passwordExpiring || passwordExpired) {
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag("password_expiration") == null) {
PasswordExpirationDialog dialog =
PasswordExpirationDialog.newInstance(mAccount.getDisplayName(),
passwordExpired);
dialog.show(fm, "password_expiration");
}
return;
}
// Otherwise, handle normal security settings flow
if (mAccount.mPolicyKey != 0) {
// This account wants to control security
if (showDialog) {
// Show dialog first, unless already showing (e.g. after rotation)
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag("security_needed") == null) {
SecurityNeededDialog dialog =
SecurityNeededDialog.newInstance(mAccount.getDisplayName());
dialog.show(fm, "security_needed");
}
} else {
// Go directly to security settings
tryAdvanceSecurity(mAccount);
}
return;
}
finish();
} else {
// Go directly to security settings
tryAdvanceSecurity(mAccount);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return;
}
finish();
}
/**
@ -229,7 +216,7 @@ public class AccountSecurity extends Activity {
Log.d(TAG, "Security active; clear holds");
}
Account.clearSecurityHoldOnAllAccounts(this);
security.clearNotification(account.mId);
security.clearNotification();
finish();
return;
}
@ -286,7 +273,7 @@ public class AccountSecurity extends Activity {
Log.d(TAG, "Policies enforced; clear holds");
}
Account.clearSecurityHoldOnAllAccounts(this);
security.clearNotification(account.mId);
security.clearNotification();
finish();
}
@ -295,6 +282,7 @@ public class AccountSecurity extends Activity {
* eventually.
*/
private void repostNotification(final Account account, final SecurityPolicy security) {
if (account == null) return;
Utility.runAsync(new Runnable() {
@Override
public void run() {