Fix ANRs from Email.setServicesEnabled()
* Create sync & async versions * Rename all callsites so sync is very apparent * Fix callsites appropriately * Clean up interaction between reconciler and setServicesEnabled Bug: 3133770 Bug: 3134677 Change-Id: Iefbc7814d9aa390baea6345e450e2a4768bf0a9a
This commit is contained in:
parent
6aec257fe7
commit
2959a7e073
|
@ -72,7 +72,7 @@ public class AccountBackupRestore {
|
||||||
// update security profile
|
// update security profile
|
||||||
SecurityPolicy.getInstance(context).updatePolicies(-1);
|
SecurityPolicy.getInstance(context).updatePolicies(-1);
|
||||||
// enable/disable other email services as necessary
|
// enable/disable other email services as necessary
|
||||||
Email.setServicesEnabled(context);
|
Email.setServicesEnabledSync(context);
|
||||||
ExchangeUtils.startExchangeService(context);
|
ExchangeUtils.startExchangeService(context);
|
||||||
}
|
}
|
||||||
sBackupsChecked = true;
|
sBackupsChecked = true;
|
||||||
|
|
|
@ -963,7 +963,7 @@ public class Controller {
|
||||||
// Release or relax device administration, if relevant
|
// Release or relax device administration, if relevant
|
||||||
SecurityPolicy.getInstance(context).reducePolicies();
|
SecurityPolicy.getInstance(context).reducePolicies();
|
||||||
|
|
||||||
Email.setServicesEnabled(context);
|
Email.setServicesEnabledSync(context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(Email.LOG_TAG, "Exception while deleting account", e);
|
Log.w(Email.LOG_TAG, "Exception while deleting account", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -175,12 +175,32 @@ public class Email extends Application {
|
||||||
return sTempDirectory;
|
return sTempDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous version of {@link #setServicesEnabledSync(Context)}. Use when calling from
|
||||||
|
* UI thread (or lifecycle entry points.)
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
public static void setServicesEnabledAsync(final Context context) {
|
||||||
|
Utility.runAsync(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setServicesEnabledSync(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called throughout the application when the number of accounts has changed. This method
|
* Called throughout the application when the number of accounts has changed. This method
|
||||||
* enables or disables the Compose activity, the boot receiver and the service based on
|
* enables or disables the Compose activity, the boot receiver and the service based on
|
||||||
* whether any accounts are configured. Returns true if there are any accounts configured.
|
* whether any accounts are configured.
|
||||||
|
*
|
||||||
|
* Blocking call - do not call from UI/lifecycle threads.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return true if there are any accounts configured.
|
||||||
*/
|
*/
|
||||||
public static boolean setServicesEnabled(Context context) {
|
public static boolean setServicesEnabledSync(Context context) {
|
||||||
Cursor c = null;
|
Cursor c = null;
|
||||||
try {
|
try {
|
||||||
c = context.getContentResolver().query(
|
c = context.getContentResolver().query(
|
||||||
|
@ -197,7 +217,7 @@ public class Email extends Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setServicesEnabled(Context context, boolean enabled) {
|
private static void setServicesEnabled(Context context, boolean enabled) {
|
||||||
PackageManager pm = context.getPackageManager();
|
PackageManager pm = context.getPackageManager();
|
||||||
if (!enabled && pm.getComponentEnabledSetting(
|
if (!enabled && pm.getComponentEnabledSetting(
|
||||||
new ComponentName(context, MailService.class)) ==
|
new ComponentName(context, MailService.class)) ==
|
||||||
|
|
|
@ -410,7 +410,7 @@ public class UpgradeAccounts extends ListActivity implements OnClickListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Enable app-wide features such as composer, and start mail service(s)
|
// Step 4: Enable app-wide features such as composer, and start mail service(s)
|
||||||
Email.setServicesEnabled(mContext);
|
Email.setServicesEnabledSync(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -620,12 +620,7 @@ public class AccountSettingsFragment extends PreferenceFragment {
|
||||||
mAccount.update(mContext, cv);
|
mAccount.update(mContext, cv);
|
||||||
|
|
||||||
// Run the remaining changes off-thread
|
// Run the remaining changes off-thread
|
||||||
Utility.runAsync(new Runnable() {
|
Email.setServicesEnabledAsync(mContext);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Email.setServicesEnabled(mContext);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -223,12 +223,15 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
|
||||||
saveAccountAndFinish();
|
saveAccountAndFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STOPSHIP most of this work needs to be async
|
||||||
|
*/
|
||||||
private void saveAccountAndFinish() {
|
private void saveAccountAndFinish() {
|
||||||
// Clear the incomplete/security hold flag now
|
// Clear the incomplete/security hold flag now
|
||||||
Account account = SetupData.getAccount();
|
Account account = SetupData.getAccount();
|
||||||
account.mFlags &= ~(Account.FLAGS_INCOMPLETE | Account.FLAGS_SECURITY_HOLD);
|
account.mFlags &= ~(Account.FLAGS_INCOMPLETE | Account.FLAGS_SECURITY_HOLD);
|
||||||
AccountSettingsUtils.commitSettings(this, account);
|
AccountSettingsUtils.commitSettings(this, account);
|
||||||
Email.setServicesEnabled(this);
|
Email.setServicesEnabledSync(this);
|
||||||
AccountSetupNames.actionSetNames(this);
|
AccountSetupNames.actionSetNames(this);
|
||||||
// Start up ExchangeService (if it isn't already running)
|
// Start up ExchangeService (if it isn't already running)
|
||||||
ExchangeUtils.startExchangeService(this);
|
ExchangeUtils.startExchangeService(this);
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class EmailBroadcastProcessorService extends IntentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableComponentsIfNecessary() {
|
private void enableComponentsIfNecessary() {
|
||||||
if (Email.setServicesEnabled(this)) {
|
if (Email.setServicesEnabledSync(this)) {
|
||||||
// At least one account exists.
|
// At least one account exists.
|
||||||
// TODO probably we should check if it's a POP/IMAP account.
|
// TODO probably we should check if it's a POP/IMAP account.
|
||||||
MailService.actionReschedule(this);
|
MailService.actionReschedule(this);
|
||||||
|
|
|
@ -1046,36 +1046,34 @@ public class ExchangeService extends Service implements Runnable {
|
||||||
*/
|
*/
|
||||||
public class EasAccountsUpdatedListener implements OnAccountsUpdateListener {
|
public class EasAccountsUpdatedListener implements OnAccountsUpdateListener {
|
||||||
public void onAccountsUpdated(android.accounts.Account[] accounts) {
|
public void onAccountsUpdated(android.accounts.Account[] accounts) {
|
||||||
ExchangeService exchangeService = INSTANCE;
|
final ExchangeService exchangeService = INSTANCE;
|
||||||
if (exchangeService != null) {
|
if (exchangeService != null) {
|
||||||
exchangeService.runAccountReconciler();
|
Utility.runAsync(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
exchangeService.runAccountReconcilerSync(exchangeService);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-blocking call to run the account reconciler.
|
* Blocking call to the account reconciler
|
||||||
* Launches a worker thread, so it may be called from UI thread.
|
|
||||||
*/
|
*/
|
||||||
private void runAccountReconciler() {
|
private void runAccountReconcilerSync(Context context) {
|
||||||
final ExchangeService exchangeService = this;
|
android.accounts.Account[] accountMgrList = AccountManager.get(context)
|
||||||
new Thread() {
|
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
|
||||||
@Override
|
synchronized (mAccountList) {
|
||||||
public void run() {
|
// Make sure we have an up-to-date sAccountList. If not (for example, if the
|
||||||
android.accounts.Account[] accountMgrList = AccountManager.get(exchangeService)
|
// service has been destroyed), we would be reconciling against an empty account
|
||||||
.getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
|
// list, which would cause the deletion of all of our accounts
|
||||||
synchronized (mAccountList) {
|
if (mAccountObserver != null) {
|
||||||
// Make sure we have an up-to-date sAccountList. If not (for example, if the
|
mAccountObserver.onAccountChanged();
|
||||||
// service has been destroyed), we would be reconciling against an empty account
|
MailService.reconcileAccountsWithAccountManager(context,
|
||||||
// list, which would cause the deletion of all of our accounts
|
mAccountList, accountMgrList, false, mResolver);
|
||||||
if (mAccountObserver != null) {
|
|
||||||
mAccountObserver.onAccountChanged();
|
|
||||||
MailService.reconcileAccountsWithAccountManager(exchangeService,
|
|
||||||
mAccountList, accountMgrList, false, mResolver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.start();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(String str) {
|
public static void log(String str) {
|
||||||
|
@ -1752,7 +1750,6 @@ public class ExchangeService extends Service implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
synchronized (sSyncLock) {
|
synchronized (sSyncLock) {
|
||||||
Email.setServicesEnabled(this);
|
|
||||||
alwaysLog("!!! EAS ExchangeService, onCreate");
|
alwaysLog("!!! EAS ExchangeService, onCreate");
|
||||||
if (sStop) {
|
if (sStop) {
|
||||||
return;
|
return;
|
||||||
|
@ -1765,9 +1762,17 @@ public class ExchangeService extends Service implements Runnable {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Run the reconciler and clean up any mismatched accounts - if we weren't running when
|
// Finally, run some setup activities off the UI thread
|
||||||
// accounts were deleted, it won't have been called.
|
Utility.runAsync(new Runnable() {
|
||||||
runAccountReconciler();
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Run the reconciler and clean up any mismatched accounts - if we weren't
|
||||||
|
// running when accounts were deleted, it won't have been called.
|
||||||
|
runAccountReconcilerSync(ExchangeService.this);
|
||||||
|
// Update other services depending on final account configuration
|
||||||
|
Email.setServicesEnabledSync(ExchangeService.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class MessageComposeTests
|
||||||
}
|
}
|
||||||
Account account = Account.restoreAccountWithId(mContext, accountId);
|
Account account = Account.restoreAccountWithId(mContext, accountId);
|
||||||
mSignature = account.getSignature();
|
mSignature = account.getSignature();
|
||||||
Email.setServicesEnabled(mContext);
|
Email.setServicesEnabledSync(mContext);
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
setActivityIntent(intent);
|
setActivityIntent(intent);
|
||||||
|
|
Loading…
Reference in New Issue