From 34662f11b2ff38f05219415f3672a52a7af2338f Mon Sep 17 00:00:00 2001 From: Tony Mantler Date: Tue, 26 Nov 2013 11:33:48 -0800 Subject: [PATCH] Save policy when saving account Also add a loader to AccountSecurity, and ignore when a policy contains unsupported requirements. b/11790165 Change-Id: Idd651153848eea3216656047c5aba3bbd750ca0a --- .../emailcommon/service/IPolicyService.aidl | 3 + .../service/PolicyServiceProxy.java | 18 +++- src/com/android/email/SecurityPolicy.java | 24 +++-- .../email/activity/setup/AccountSecurity.java | 88 +++++++++++++++++-- .../activity/setup/AccountSettingsUtils.java | 18 ++++ .../android/email/service/PolicyService.java | 9 +- 6 files changed, 143 insertions(+), 17 deletions(-) diff --git a/emailcommon/src/com/android/emailcommon/service/IPolicyService.aidl b/emailcommon/src/com/android/emailcommon/service/IPolicyService.aidl index 9d4be36e4..c284292e0 100755 --- a/emailcommon/src/com/android/emailcommon/service/IPolicyService.aidl +++ b/emailcommon/src/com/android/emailcommon/service/IPolicyService.aidl @@ -20,6 +20,9 @@ import com.android.emailcommon.provider.Policy; interface IPolicyService { boolean isActive(in Policy policies); void setAccountHoldFlag(long accountId, boolean newState); + // Legacy compatability for Exchange shipped with KK void setAccountPolicy(long accountId, in Policy policy, String securityKey); + // New version + void setAccountPolicy2(long accountId, in Policy policy, String securityKey, boolean notify); oneway void remoteWipe(); } \ No newline at end of file diff --git a/emailcommon/src/com/android/emailcommon/service/PolicyServiceProxy.java b/emailcommon/src/com/android/emailcommon/service/PolicyServiceProxy.java index 347768b10..fcd916f25 100755 --- a/emailcommon/src/com/android/emailcommon/service/PolicyServiceProxy.java +++ b/emailcommon/src/com/android/emailcommon/service/PolicyServiceProxy.java @@ -70,12 +70,18 @@ public class PolicyServiceProxy extends ServiceProxy implements IPolicyService { @Override public void setAccountPolicy(final long accountId, final Policy policy, final String securityKey) throws RemoteException { + setAccountPolicy2(accountId, policy, securityKey, true /* notify */); + } + + @Override + public void setAccountPolicy2(final long accountId, final Policy policy, + final String securityKey, final boolean notify) throws RemoteException { setTask(new ProxyTask() { @Override public void run() throws RemoteException { - mService.setAccountPolicy(accountId, policy, securityKey); + mService.setAccountPolicy2(accountId, policy, securityKey, notify); } - }, "setAccountPolicy"); + }, "setAccountPolicy2"); waitForCompletion(); } @@ -126,8 +132,14 @@ public class PolicyServiceProxy extends ServiceProxy implements IPolicyService { public static void setAccountPolicy(Context context, long accountId, Policy policy, String securityKey) { + setAccountPolicy2(context, accountId, policy, securityKey, true /* notify */); + } + + public static void setAccountPolicy2(Context context, long accountId, Policy policy, + String securityKey, boolean notify) { try { - new PolicyServiceProxy(context).setAccountPolicy(accountId, policy, securityKey); + new PolicyServiceProxy(context).setAccountPolicy2(accountId, policy, securityKey, + notify); return; } catch (RemoteException e) { } diff --git a/src/com/android/email/SecurityPolicy.java b/src/com/android/email/SecurityPolicy.java index de1b31dfa..de1a04eaf 100644 --- a/src/com/android/email/SecurityPolicy.java +++ b/src/com/android/email/SecurityPolicy.java @@ -583,7 +583,8 @@ public class SecurityPolicy { syncAccount(mContext, account); } - public void setAccountPolicy(long accountId, Policy policy, String securityKey) { + public void setAccountPolicy(long accountId, Policy policy, String securityKey, + boolean notify) { Account account = Account.restoreAccountWithId(mContext, accountId); Policy oldPolicy = null; if (account.mPolicyKey > 0) { @@ -613,8 +614,10 @@ public class SecurityPolicy { LogUtils.d(Logging.LOG_TAG, "Notify policies for " + account.mDisplayName + " not supported."); setHold = true; - NotificationController.getInstance(mContext).showSecurityUnsupportedNotification( - account); + if (notify) { + NotificationController.getInstance(mContext).showSecurityUnsupportedNotification( + account); + } // Erase data Uri uri = EmailProvider.uiUri("uiaccountdata", accountId); mContext.getContentResolver().delete(uri, null, null); @@ -622,9 +625,11 @@ public class SecurityPolicy { if (policyChanged) { LogUtils.d(Logging.LOG_TAG, "Notify policies for " + account.mDisplayName + " changed."); - // Notify that policies changed - NotificationController.getInstance(mContext).showSecurityChangedNotification( - account); + if (notify) { + // Notify that policies changed + NotificationController.getInstance(mContext).showSecurityChangedNotification( + account); + } } else { LogUtils.d(Logging.LOG_TAG, "Policy is active and unchanged; do not notify."); } @@ -632,8 +637,11 @@ public class SecurityPolicy { setHold = true; LogUtils.d(Logging.LOG_TAG, "Notify policies for " + account.mDisplayName + " are not being enforced."); - // Put up a notification - NotificationController.getInstance(mContext).showSecurityNeededNotification(account); + if (notify) { + // Put up a notification + NotificationController.getInstance(mContext).showSecurityNeededNotification( + account); + } } // Set/clear the account hold. setAccountHoldFlag(mContext, account, setHold); diff --git a/src/com/android/email/activity/setup/AccountSecurity.java b/src/com/android/email/activity/setup/AccountSecurity.java index c25d26ec7..8736599bb 100644 --- a/src/com/android/email/activity/setup/AccountSecurity.java +++ b/src/com/android/email/activity/setup/AccountSecurity.java @@ -21,19 +21,25 @@ import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.FragmentManager; +import android.app.LoaderManager; import android.app.admin.DevicePolicyManager; +import android.content.AsyncTaskLoader; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.Loader; import android.content.res.Resources; import android.os.Bundle; +import android.text.TextUtils; +import com.android.email.NotificationController; import com.android.email.R; import com.android.email.SecurityPolicy; import com.android.email.activity.ActivityHelper; import com.android.email2.ui.MailActivityEmail; import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.HostAuth; +import com.android.emailcommon.provider.Policy; import com.android.emailcommon.utility.Utility; import com.android.mail.utils.LogUtils; @@ -99,6 +105,8 @@ public class AccountSecurity extends Activity { return intent; } + private static final int ACCOUNT_POLICY_LOADER = 0; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -116,11 +124,81 @@ public class AccountSecurity extends Activity { return; } - mAccount = Account.restoreAccountWithId(AccountSecurity.this, accountId); - if (mAccount == null) { - finish(); - return; - } + final Bundle b = new Bundle(1); + b.putLong(EXTRA_ACCOUNT_ID, accountId); + + getLoaderManager().initLoader(ACCOUNT_POLICY_LOADER, b, + new LoaderManager.LoaderCallbacks() { + @Override + public Loader onCreateLoader(final int id, final Bundle args) { + final long accountId = args.getLong(EXTRA_ACCOUNT_ID); + return new AsyncTaskLoader(AccountSecurity.this) { + volatile Account mData; + + @Override + public Account loadInBackground() { + final Account account = Account.restoreAccountWithId(AccountSecurity.this, + accountId); + if (account == null) { + return null; + } + + final long policyId = account.mPolicyKey; + + if (policyId == 0) { + return account; + } + + account.mPolicy = Policy.restorePolicyWithId(AccountSecurity.this, + policyId); + return account; + } + + @Override + public void deliverResult(final Account data) { + if (isStarted()) { + super.deliverResult(data); + } else { + mData = data; + } + } + + @Override + protected void onStartLoading() { + if (mData != null) { + deliverResult(mData); + } else { + forceLoad(); + } + } + + @Override + protected void onStopLoading() { + cancelLoad(); + } + }; + } + + @Override + public void onLoadFinished(final Loader loader, final Account data) { + if (data == null || (data.mPolicyKey != 0 && data.mPolicy == null)) { + finish(); + LogUtils.d(TAG, "could not load account or policy in AccountSecurity"); + return; + } + finishCreate(data, showDialog, passwordExpiring, passwordExpired); + getLoaderManager().destroyLoader(ACCOUNT_POLICY_LOADER); + } + + @Override + public void onLoaderReset(final Loader loader) { + } + }); + } + + private void finishCreate(final Account account, final boolean showDialog, + final boolean passwordExpiring, final boolean passwordExpired) { + mAccount = account; // Special handling for password expiration events if (passwordExpiring || passwordExpired) { diff --git a/src/com/android/email/activity/setup/AccountSettingsUtils.java b/src/com/android/email/activity/setup/AccountSettingsUtils.java index a2234c26d..550566382 100644 --- a/src/com/android/email/activity/setup/AccountSettingsUtils.java +++ b/src/com/android/email/activity/setup/AccountSettingsUtils.java @@ -25,6 +25,7 @@ import android.text.TextUtils; import android.widget.EditText; import com.android.email.R; +import com.android.email.SecurityPolicy; import com.android.email.provider.AccountBackupRestore; import com.android.emailcommon.Logging; import com.android.emailcommon.VendorPolicyLoader; @@ -32,6 +33,7 @@ import com.android.emailcommon.VendorPolicyLoader.Provider; import com.android.emailcommon.provider.Account; import com.android.emailcommon.provider.EmailContent.AccountColumns; import com.android.emailcommon.provider.QuickResponse; +import com.android.emailcommon.service.PolicyServiceProxy; import com.android.emailcommon.utility.Utility; import com.android.mail.utils.LogUtils; import com.google.common.annotations.VisibleForTesting; @@ -55,6 +57,22 @@ public class AccountSettingsUtils { if (!account.isSaved()) { account.save(context); + if (account.mPolicy != null) { + // TODO: we need better handling for unsupported policies + // For now, just clear the unsupported policies, as the server will (hopefully) + // just reject our sync attempts if it's not happy with half-measures + if (account.mPolicy.mProtocolPoliciesUnsupported != null) { + LogUtils.d(LogUtils.TAG, "Clearing unsupported policies " + + account.mPolicy.mProtocolPoliciesUnsupported); + account.mPolicy.mProtocolPoliciesUnsupported = null; + } + PolicyServiceProxy.setAccountPolicy2(context, + account.getId(), + account.mPolicy, + account.mSecuritySyncKey == null ? "" : account.mSecuritySyncKey, + false /* notify */); + } + // Set up default quick responses here... String[] defaultQuickResponses = context.getResources().getStringArray(R.array.default_quick_responses); diff --git a/src/com/android/email/service/PolicyService.java b/src/com/android/email/service/PolicyService.java index aa4fdeff7..c045fabab 100644 --- a/src/com/android/email/service/PolicyService.java +++ b/src/com/android/email/service/PolicyService.java @@ -20,6 +20,7 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.IBinder; +import android.os.RemoteException; import com.android.email.SecurityPolicy; import com.android.emailcommon.provider.Policy; @@ -65,8 +66,14 @@ public class PolicyService extends Service { @Override public void setAccountPolicy(long accountId, Policy policy, String securityKey) { + setAccountPolicy2(accountId, policy, securityKey, true /* notify */); + } + + @Override + public void setAccountPolicy2(long accountId, Policy policy, String securityKey, + boolean notify) { try { - mSecurityPolicy.setAccountPolicy(accountId, policy, securityKey); + mSecurityPolicy.setAccountPolicy(accountId, policy, securityKey, notify); } catch (RuntimeException e) { // Catch, log and rethrow the exception, as otherwise when the exception is // ultimately handled, the complete stack trace is losk