19fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki/* 29fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * Copyright (C) 2010 The Android Open Source Project 39fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * 49fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 59fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * you may not use this file except in compliance with the License. 69fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * You may obtain a copy of the License at 79fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * 89fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 99fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * 109fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * Unless required by applicable law or agreed to in writing, software 119fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 129fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * See the License for the specific language governing permissions and 149fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki * limitations under the License. 159fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki */ 169fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki 1766a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blankpackage com.android.email.service; 189fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki 1970edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.accounts.AccountManager; 2002f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Huimport android.accounts.AccountManagerCallback; 2170edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.accounts.AccountManagerFuture; 2270edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.accounts.AuthenticatorException; 2370edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.accounts.OperationCanceledException; 2403cd72805dab0379ed255d151f1c17cc60655fc3Marc Blankimport android.app.Service; 2574dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdonimport android.content.ComponentName; 26e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport android.content.ContentProviderClient; 2770edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.content.ContentResolver; 2870edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.content.ContentUris; 2970edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.content.ContentValues; 309fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onukiimport android.content.Context; 319fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onukiimport android.content.Intent; 323a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantlerimport android.content.pm.ActivityInfo; 3374dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdonimport android.content.pm.PackageManager; 343a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantlerimport android.content.res.Configuration; 35f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport android.content.res.Resources; 36f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport android.content.res.TypedArray; 37f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport android.content.res.XmlResourceParser; 3870edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.database.Cursor; 3970edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.net.Uri; 4003cd72805dab0379ed255d151f1c17cc60655fc3Marc Blankimport android.os.Bundle; 4103cd72805dab0379ed255d151f1c17cc60655fc3Marc Blankimport android.os.IBinder; 4203cd72805dab0379ed255d151f1c17cc60655fc3Marc Blankimport android.os.RemoteException; 4370edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.provider.CalendarContract; 44e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport android.provider.CalendarContract.Calendars; 45e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport android.provider.CalendarContract.SyncState; 4670edcf05387df33f4761b766add6b80999e425e9Marc Blankimport android.provider.ContactsContract; 473aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdonimport android.provider.ContactsContract.RawContacts; 48e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport android.provider.SyncStateContract; 494c865846856cd7530fb51e244a9971a3d5e1fcd8Tony Mantlerimport android.support.annotation.Nullable; 5053b64eee54cdb74dc325089b8362a6ff4811759eTony Mantlerimport android.text.TextUtils; 51e1a6088ee4e3f0e4344dd9bc38029b6d01431eabMarc Blank 52f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.email.R; 53ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Leeimport com.android.emailcommon.VendorPolicyLoader; 54f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.emailcommon.provider.Account; 5570edcf05387df33f4761b766add6b80999e425e9Marc Blankimport com.android.emailcommon.provider.EmailContent; 5670edcf05387df33f4761b766add6b80999e425e9Marc Blankimport com.android.emailcommon.provider.EmailContent.AccountColumns; 573dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantlerimport com.android.emailcommon.provider.EmailContent.HostAuthColumns; 58e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport com.android.emailcommon.provider.HostAuth; 5966a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blankimport com.android.emailcommon.service.EmailServiceProxy; 60fb2a3a2f77f954265beaa92b87774006e2d7c185Martin Hibdonimport com.android.emailcommon.service.EmailServiceStatus; 617afbeee47e1a82680c815f2fb8cfdba32d6b0b84Martin Hibdonimport com.android.emailcommon.service.EmailServiceVersion; 621d8fd9c05449863ac6a151a6db87c267c4f55ac2Martin Hibdonimport com.android.emailcommon.service.HostAuthCompat; 6366a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blankimport com.android.emailcommon.service.IEmailService; 6466a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blankimport com.android.emailcommon.service.IEmailServiceCallback; 6503cd72805dab0379ed255d151f1c17cc60655fc3Marc Blankimport com.android.emailcommon.service.SearchParams; 6624bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdonimport com.android.emailcommon.service.ServiceProxy; 67f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.emailcommon.service.SyncWindow; 68560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils; 69b5eed31d1bdfcb8e8b316c9c49331295718001bdYu Ping Huimport com.google.common.collect.ImmutableMap; 70462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu 71f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport org.xmlpull.v1.XmlPullParserException; 72f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 73f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport java.io.IOException; 74b5eed31d1bdfcb8e8b316c9c49331295718001bdYu Ping Huimport java.util.Collection; 7532881e8dd375f16e6059452166503f7136f14ae5Paul Westbrookimport java.util.Map; 7666a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank 779fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki/** 7866a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank * Utility functions for EmailService support. 799fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki */ 8066a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blankpublic class EmailServiceUtils { 819fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki /** 8224bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon * Ask a service to kill its process. This is used when an account is deleted so that 8324bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon * no background thread that happens to be running will continue, possibly hitting an 8424bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon * NPE or other error when trying to operate on an account that no longer exists. 8524bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon * TODO: This is kind of a hack, it's only needed because we fail so badly if an account 8624bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon * is deleted out from under us while a sync or other operation is in progress. It would 8724bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon * be a lot cleaner if our background services could handle this without crashing. 8824bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon */ 8924bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon public static void killService(Context context, String protocol) { 9024bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon EmailServiceInfo info = getServiceInfo(context, protocol); 9124bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon if (info != null && info.intentAction != null) { 9224bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon final Intent serviceIntent = getServiceIntent(info); 9324bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon serviceIntent.putExtra(ServiceProxy.EXTRA_FORCE_SHUTDOWN, true); 9424bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon context.startService(serviceIntent); 9524bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon } 9624bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon } 9724bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon 9824bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon /** 99f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * Starts an EmailService by protocol 1009fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki */ 101f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public static void startService(Context context, String protocol) { 102f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank EmailServiceInfo info = getServiceInfo(context, protocol); 103f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (info != null && info.intentAction != null) { 104e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook final Intent serviceIntent = getServiceIntent(info); 105e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook context.startService(serviceIntent); 106f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 1079fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki } 1089fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki 1099fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki /** 110f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * Starts all remote services 1119fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki */ 112f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public static void startRemoteServices(Context context) { 113f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank for (EmailServiceInfo info: getServiceInfoList(context)) { 114f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (info.intentAction != null) { 115e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook final Intent serviceIntent = getServiceIntent(info); 116e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook context.startService(serviceIntent); 117f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 118f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 119f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 120f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 121f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank /** 122f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * Returns whether or not remote services are present on device 123f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank */ 124f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public static boolean areRemoteServicesInstalled(Context context) { 125f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank for (EmailServiceInfo info: getServiceInfoList(context)) { 126f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (info.intentAction != null) { 127f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank return true; 128f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 129f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 130f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank return false; 131f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 132f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 133f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank /** 134f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * Starts all remote services 135f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank */ 136f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public static void setRemoteServicesLogging(Context context, int debugBits) { 137f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank for (EmailServiceInfo info: getServiceInfoList(context)) { 138f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (info.intentAction != null) { 139f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank EmailServiceProxy service = 1402075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu EmailServiceUtils.getService(context, info.protocol); 141f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (service != null) { 142f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank try { 143f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank service.setLogging(debugBits); 144f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } catch (RemoteException e) { 145f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank // Move along, nothing to see 146f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 147f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 148f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 149f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 1503a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 1513a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 1523a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank /** 15366a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank * Determine if the EmailService is available 1543a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank */ 155f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public static boolean isServiceAvailable(Context context, String protocol) { 156f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank EmailServiceInfo info = getServiceInfo(context, protocol); 157f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (info == null) return false; 158f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank if (info.klass != null) return true; 159e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook final Intent serviceIntent = getServiceIntent(info); 160e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook return new EmailServiceProxy(context, serviceIntent).test(); 161e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook } 162e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook 163e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook private static Intent getServiceIntent(EmailServiceInfo info) { 164e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook final Intent serviceIntent = new Intent(info.intentAction); 165e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook serviceIntent.setPackage(info.intentPackage); 166e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook return serviceIntent; 167f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 168f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 169f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank /** 170f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * For a given account id, return a service proxy if applicable, or null. 171f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * 172f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * @param accountId the message of interest 1733a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler * @return service proxy, or null if n/a 174f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank */ 1752075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu public static EmailServiceProxy getServiceForAccount(Context context, long accountId) { 1762075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu return getService(context, Account.getProtocol(context, accountId)); 177f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 178f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 179f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank /** 180f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * Holder of service information (currently just name and class/intent); if there is a class 181f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * member, this is a (local, i.e. same process) service; otherwise, this is a remote service 182f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank */ 183f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public static class EmailServiceInfo { 184f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public String protocol; 185f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public String name; 186f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public String accountType; 187f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank Class<? extends Service> klass; 188f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank String intentAction; 189e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook String intentPackage; 190f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public int port; 191f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public int portSsl; 192f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean defaultSsl; 193f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean offerTls; 194f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean offerCerts; 1959195a1202483053606f43e871915a5405e955306Martin Hibdon public boolean offerOAuth; 196f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean usesSmtp; 197f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean offerLocalDeletes; 198f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public int defaultLocalDeletes; 199f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean offerPrefix; 200f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean usesAutodiscover; 201f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean offerLookback; 202f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public int defaultLookback; 203f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean syncChanges; 204f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean syncContacts; 205f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean syncCalendar; 206f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public boolean offerAttachmentPreload; 207f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public CharSequence[] syncIntervalStrings; 208f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public CharSequence[] syncIntervals; 209f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public int defaultSyncInterval; 210b89744ecfb92a4b8fc66a23b942531d39910de44Marc Blank public String inferPrefix; 211b82ae909d7514bf06090ee3a120aef2154ab0296Marc Blank public boolean offerLoadMore; 212ae46818a1925cc22fe20ee26ffee8779561a903bAlon Albert public boolean offerMoveTo; 21381b0f74efa39d80b0aa18686c96499faf0e2691fMarc Blank public boolean requiresSetup; 2145c523858385176c33a7456bb84035de78552d22dMarc Blank public boolean hide; 215751da261722f6b8964c9a4f4b198aeb730addb50Tony Mantler public boolean isGmailStub; 216f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 2175c523858385176c33a7456bb84035de78552d22dMarc Blank @Override 218f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public String toString() { 219f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank StringBuilder sb = new StringBuilder("Protocol: "); 220f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank sb.append(protocol); 221f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank sb.append(", "); 222f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank sb.append(klass != null ? "Local" : "Remote"); 223af092bd5f850653b0d237fb55ccc896f74dc7982Marc Blank sb.append(" , Account Type: "); 224af092bd5f850653b0d237fb55ccc896f74dc7982Marc Blank sb.append(accountType); 225f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank return sb.toString(); 226f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 22791237e9dcb0a948f17488b464edabcea0f259d31Makoto Onuki } 22891237e9dcb0a948f17488b464edabcea0f259d31Makoto Onuki 2292075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu public static EmailServiceProxy getService(Context context, String protocol) { 230cf3b3ae987e73453f2265673a7ba3a72a1a6b4edMarc Blank EmailServiceInfo info = null; 231f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank // Handle the degenerate case here (account might have been deleted) 232cf3b3ae987e73453f2265673a7ba3a72a1a6b4edMarc Blank if (protocol != null) { 233cf3b3ae987e73453f2265673a7ba3a72a1a6b4edMarc Blank info = getServiceInfo(context, protocol); 234cf3b3ae987e73453f2265673a7ba3a72a1a6b4edMarc Blank } 235cf3b3ae987e73453f2265673a7ba3a72a1a6b4edMarc Blank if (info == null) { 23684e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Returning NullService for %s", protocol); 2372075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu return new EmailServiceProxy(context, NullService.class); 238e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } else { 2392075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu return getServiceFromInfo(context, info); 240e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 241e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 242e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank 2432075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu public static EmailServiceProxy getServiceFromInfo(Context context, EmailServiceInfo info) { 244e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank if (info.klass != null) { 2452075c97f608a853923980865b72147a5c8ef71f0Yu Ping Hu return new EmailServiceProxy(context, info.klass); 246f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } else { 247e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook final Intent serviceIntent = getServiceIntent(info); 248e4ac06080ba8b8e57531982ea290354b1a9a4305Paul Westbrook return new EmailServiceProxy(context, serviceIntent); 249f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 25066a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank } 25166a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank 25281b0f74efa39d80b0aa18686c96499faf0e2691fMarc Blank public static EmailServiceInfo getServiceInfoForAccount(Context context, long accountId) { 25381b0f74efa39d80b0aa18686c96499faf0e2691fMarc Blank String protocol = Account.getProtocol(context, accountId); 25481b0f74efa39d80b0aa18686c96499faf0e2691fMarc Blank return getServiceInfo(context, protocol); 25581b0f74efa39d80b0aa18686c96499faf0e2691fMarc Blank } 25681b0f74efa39d80b0aa18686c96499faf0e2691fMarc Blank 2573a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler public static EmailServiceInfo getServiceInfo(Context context, String protocol) { 2583a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler return getServiceMap(context).get(protocol); 25966a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank } 26066a47b8dac5e97e37c30b928bc5a227d74baada9Marc Blank 2613a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler public static Collection<EmailServiceInfo> getServiceInfoList(Context context) { 2623a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler return getServiceMap(context).values(); 263c18f8f615f134a2b391d06e2d8d49434a8bb94e5Makoto Onuki } 264c18f8f615f134a2b391d06e2d8d49434a8bb94e5Makoto Onuki 26570edcf05387df33f4761b766add6b80999e425e9Marc Blank private static void finishAccountManagerBlocker(AccountManagerFuture<?> future) { 26670edcf05387df33f4761b766add6b80999e425e9Marc Blank try { 26770edcf05387df33f4761b766add6b80999e425e9Marc Blank // Note: All of the potential errors are simply logged 26870edcf05387df33f4761b766add6b80999e425e9Marc Blank // here, as there is nothing to actually do about them. 26970edcf05387df33f4761b766add6b80999e425e9Marc Blank future.getResult(); 27070edcf05387df33f4761b766add6b80999e425e9Marc Blank } catch (OperationCanceledException e) { 27184e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, e, "finishAccountManagerBlocker"); 27270edcf05387df33f4761b766add6b80999e425e9Marc Blank } catch (AuthenticatorException e) { 27384e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, e, "finishAccountManagerBlocker"); 27470edcf05387df33f4761b766add6b80999e425e9Marc Blank } catch (IOException e) { 27584e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, e, "finishAccountManagerBlocker"); 27670edcf05387df33f4761b766add6b80999e425e9Marc Blank } 27770edcf05387df33f4761b766add6b80999e425e9Marc Blank } 27870edcf05387df33f4761b766add6b80999e425e9Marc Blank 27902f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu /** 28002f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * Add an account to the AccountManager. 28102f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @param context Our {@link Context}. 28202f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @param account The {@link Account} we're adding. 28302f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @param email Whether the user wants to sync email on this account. 28402f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @param calendar Whether the user wants to sync calendar on this account. 28502f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @param contacts Whether the user wants to sync contacts on this account. 28602f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @param callback A callback for when the AccountManager is done. 28702f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu * @return The result of {@link AccountManager#addAccount}. 28802f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu */ 28902f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu public static AccountManagerFuture<Bundle> setupAccountManagerAccount(final Context context, 29002f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu final Account account, final boolean email, final boolean calendar, 29102f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu final boolean contacts, final AccountManagerCallback<Bundle> callback) { 29202f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu final HostAuth hostAuthRecv = 29302f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv); 29420110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee return setupAccountManagerAccount(context, account, email, calendar, contacts, 29520110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee hostAuthRecv, callback); 29620110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee } 29720110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee 29820110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee /** 29920110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * Add an account to the AccountManager. 30020110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param context Our {@link Context}. 30120110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param account The {@link Account} we're adding. 30220110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param email Whether the user wants to sync email on this account. 30320110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param calendar Whether the user wants to sync calendar on this account. 30420110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param contacts Whether the user wants to sync contacts on this account. 30520110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param hostAuth HostAuth that identifies the protocol and password for this account. 30620110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @param callback A callback for when the AccountManager is done. 30720110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee * @return The result of {@link AccountManager#addAccount}. 30820110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee */ 30920110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee public static AccountManagerFuture<Bundle> setupAccountManagerAccount(final Context context, 31020110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee final Account account, final boolean email, final boolean calendar, 31120110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee final boolean contacts, final HostAuth hostAuth, 31220110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee final AccountManagerCallback<Bundle> callback) { 31320110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee if (hostAuth == null) { 31402f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu return null; 31502f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu } 31602f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu // Set up username/password 31720110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee final Bundle options = new Bundle(5); 31802f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu options.putString(EasAuthenticatorService.OPTIONS_USERNAME, account.mEmailAddress); 31920110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee options.putString(EasAuthenticatorService.OPTIONS_PASSWORD, hostAuth.mPassword); 32002f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu options.putBoolean(EasAuthenticatorService.OPTIONS_CONTACTS_SYNC_ENABLED, contacts); 32102f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu options.putBoolean(EasAuthenticatorService.OPTIONS_CALENDAR_SYNC_ENABLED, calendar); 32202f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu options.putBoolean(EasAuthenticatorService.OPTIONS_EMAIL_SYNC_ENABLED, email); 32320110e628830a906f4c6a80eabb0bb127bf7d4beAnthony Lee final EmailServiceInfo info = getServiceInfo(context, hostAuth.mProtocol); 32402f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu return AccountManager.get(context).addAccount(info.accountType, null, null, options, null, 32502f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu callback, null); 32602f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu } 32702f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu 328462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu public static void updateAccountManagerType(Context context, 32948b14fde961ef57103f7a31196254e357987f203Yu Ping Hu android.accounts.Account amAccount, final Map<String, String> protocolMap) { 33032881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final ContentResolver resolver = context.getContentResolver(); 33132881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final Cursor c = resolver.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION, 33270edcf05387df33f4761b766add6b80999e425e9Marc Blank AccountColumns.EMAIL_ADDRESS + "=?", new String[] { amAccount.name }, null); 33370edcf05387df33f4761b766add6b80999e425e9Marc Blank // That's odd, isn't it? 33470edcf05387df33f4761b766add6b80999e425e9Marc Blank if (c == null) return; 33570edcf05387df33f4761b766add6b80999e425e9Marc Blank try { 33670edcf05387df33f4761b766add6b80999e425e9Marc Blank if (c.moveToNext()) { 33770edcf05387df33f4761b766add6b80999e425e9Marc Blank // Get the EmailProvider Account/HostAuth 33832881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final Account account = new Account(); 33970edcf05387df33f4761b766add6b80999e425e9Marc Blank account.restore(c); 34032881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final HostAuth hostAuth = 34170edcf05387df33f4761b766add6b80999e425e9Marc Blank HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv); 34232881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook if (hostAuth == null) { 34332881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook return; 34432881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook } 34570edcf05387df33f4761b766add6b80999e425e9Marc Blank 346462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu final String newProtocol = protocolMap.get(hostAuth.mProtocol); 347462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu if (newProtocol == null) { 348462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu // This account doesn't need updating. 349e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank return; 350e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 351462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu 35284e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Converting %s to %s", amAccount.name, newProtocol); 353e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank 35432881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final ContentValues accountValues = new ContentValues(); 35570edcf05387df33f4761b766add6b80999e425e9Marc Blank int oldFlags = account.mFlags; 35670edcf05387df33f4761b766add6b80999e425e9Marc Blank 35770edcf05387df33f4761b766add6b80999e425e9Marc Blank // Mark the provider account incomplete so it can't get reconciled away 35870edcf05387df33f4761b766add6b80999e425e9Marc Blank account.mFlags |= Account.FLAGS_INCOMPLETE; 35970edcf05387df33f4761b766add6b80999e425e9Marc Blank accountValues.put(AccountColumns.FLAGS, account.mFlags); 36032881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final Uri accountUri = ContentUris.withAppendedId(Account.CONTENT_URI, account.mId); 36170edcf05387df33f4761b766add6b80999e425e9Marc Blank resolver.update(accountUri, accountValues, null, null); 36270edcf05387df33f4761b766add6b80999e425e9Marc Blank 36370edcf05387df33f4761b766add6b80999e425e9Marc Blank // Change the HostAuth to reference the new protocol; this has to be done before 36470edcf05387df33f4761b766add6b80999e425e9Marc Blank // trying to create the AccountManager account (below) 36532881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final ContentValues hostValues = new ContentValues(); 3663dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler hostValues.put(HostAuthColumns.PROTOCOL, newProtocol); 36770edcf05387df33f4761b766add6b80999e425e9Marc Blank resolver.update(ContentUris.withAppendedId(HostAuth.CONTENT_URI, hostAuth.mId), 36870edcf05387df33f4761b766add6b80999e425e9Marc Blank hostValues, null, null); 36984e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Updated HostAuths"); 37070edcf05387df33f4761b766add6b80999e425e9Marc Blank 37170edcf05387df33f4761b766add6b80999e425e9Marc Blank try { 37270edcf05387df33f4761b766add6b80999e425e9Marc Blank // Get current settings for the existing AccountManager account 37370edcf05387df33f4761b766add6b80999e425e9Marc Blank boolean email = ContentResolver.getSyncAutomatically(amAccount, 37470edcf05387df33f4761b766add6b80999e425e9Marc Blank EmailContent.AUTHORITY); 375e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank if (!email) { 376e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank // Try our old provider name 377e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank email = ContentResolver.getSyncAutomatically(amAccount, 378e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank "com.android.email.provider"); 379e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 38032881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final boolean contacts = ContentResolver.getSyncAutomatically(amAccount, 38170edcf05387df33f4761b766add6b80999e425e9Marc Blank ContactsContract.AUTHORITY); 38232881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final boolean calendar = ContentResolver.getSyncAutomatically(amAccount, 38370edcf05387df33f4761b766add6b80999e425e9Marc Blank CalendarContract.AUTHORITY); 38484e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Email: %s, Contacts: %s Calendar: %s", 38584e010a463ea5c006d55b7e32268fed40e40262fTony Mantler email, contacts, calendar); 386e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank 387e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank // Get sync keys for calendar/contacts 38832881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final String amName = amAccount.name; 38932881e8dd375f16e6059452166503f7136f14ae5Paul Westbrook final String oldType = amAccount.type; 390e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank ContentProviderClient client = context.getContentResolver() 391e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank .acquireContentProviderClient(CalendarContract.CONTENT_URI); 392e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank byte[] calendarSyncKey = null; 393e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank try { 394e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank calendarSyncKey = SyncStateContract.Helpers.get(client, 395e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank asCalendarSyncAdapter(SyncState.CONTENT_URI, amName, oldType), 396e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank new android.accounts.Account(amName, oldType)); 397e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } catch (RemoteException e) { 39884e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Get calendar key FAILED"); 399e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } finally { 400e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank client.release(); 401e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 402e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank client = context.getContentResolver() 403e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank .acquireContentProviderClient(ContactsContract.AUTHORITY_URI); 404e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank byte[] contactsSyncKey = null; 405e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank try { 406e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank contactsSyncKey = SyncStateContract.Helpers.get(client, 407e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank ContactsContract.SyncState.CONTENT_URI, 408e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank new android.accounts.Account(amName, oldType)); 409e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } catch (RemoteException e) { 41084e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Get contacts key FAILED"); 411e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } finally { 412e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank client.release(); 413e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 414e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank if (calendarSyncKey != null) { 41584e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Got calendar key: %s", 41684e010a463ea5c006d55b7e32268fed40e40262fTony Mantler new String(calendarSyncKey)); 417e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 418e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank if (contactsSyncKey != null) { 41984e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Got contacts key: %s", 42084e010a463ea5c006d55b7e32268fed40e40262fTony Mantler new String(contactsSyncKey)); 421e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 422e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank 423e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank // Set up a new AccountManager account with new type and old settings 42402f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu AccountManagerFuture<?> amFuture = setupAccountManagerAccount(context, account, 42502f0b1eee8f5de651ad5f0289146f88fea99bce0Yu Ping Hu email, calendar, contacts, null); 426e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank finishAccountManagerBlocker(amFuture); 42784e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Created new AccountManager account"); 42870edcf05387df33f4761b766add6b80999e425e9Marc Blank 4293aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon // TODO: Clean up how we determine the type. 4303aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final String accountType = protocolMap.get(hostAuth.mProtocol + "_type"); 4313aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon // Move calendar and contacts data from the old account to the new one. 4323aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon // We must do this before deleting the old account or the data is lost. 4333aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon moveCalendarData(context.getContentResolver(), amName, oldType, accountType); 4343aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon moveContactsData(context.getContentResolver(), amName, oldType, accountType); 4357d6d8c87f86a17cae59af645637458b17e72c716Martin Hibdon 43670edcf05387df33f4761b766add6b80999e425e9Marc Blank // Delete the AccountManager account 437e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank amFuture = AccountManager.get(context) 43870edcf05387df33f4761b766add6b80999e425e9Marc Blank .removeAccount(amAccount, null, null); 43970edcf05387df33f4761b766add6b80999e425e9Marc Blank finishAccountManagerBlocker(amFuture); 44084e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Deleted old AccountManager account"); 44170edcf05387df33f4761b766add6b80999e425e9Marc Blank 442e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank // Restore sync keys for contacts/calendar 4433aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon 444462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu if (accountType != null && 445462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu calendarSyncKey != null && calendarSyncKey.length != 0) { 446e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank client = context.getContentResolver() 447e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank .acquireContentProviderClient(CalendarContract.CONTENT_URI); 448e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank try { 449e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank SyncStateContract.Helpers.set(client, 450e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank asCalendarSyncAdapter(SyncState.CONTENT_URI, amName, 451462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu accountType), 452462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu new android.accounts.Account(amName, accountType), 453e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank calendarSyncKey); 45484e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Set calendar key..."); 455e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } catch (RemoteException e) { 45684e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Set calendar key FAILED"); 457e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } finally { 458e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank client.release(); 459e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 460e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 461462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu if (accountType != null && 462462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu contactsSyncKey != null && contactsSyncKey.length != 0) { 463e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank client = context.getContentResolver() 464e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank .acquireContentProviderClient(ContactsContract.AUTHORITY_URI); 465e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank try { 466e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank SyncStateContract.Helpers.set(client, 467e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank ContactsContract.SyncState.CONTENT_URI, 468462da178b1be608a74000956c53dc8ecb438c689Yu Ping Hu new android.accounts.Account(amName, accountType), 469e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank contactsSyncKey); 47084e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Set contacts key..."); 471e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } catch (RemoteException e) { 47284e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Set contacts key FAILED"); 473e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 474e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 475e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank 476e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank // That's all folks! 47784e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "Account update completed."); 47870edcf05387df33f4761b766add6b80999e425e9Marc Blank } finally { 47970edcf05387df33f4761b766add6b80999e425e9Marc Blank // Clear the incomplete flag on the provider account 48070edcf05387df33f4761b766add6b80999e425e9Marc Blank accountValues.put(AccountColumns.FLAGS, oldFlags); 48170edcf05387df33f4761b766add6b80999e425e9Marc Blank resolver.update(accountUri, accountValues, null, null); 48284e010a463ea5c006d55b7e32268fed40e40262fTony Mantler LogUtils.w(LogUtils.TAG, "[Incomplete flag cleared]"); 48370edcf05387df33f4761b766add6b80999e425e9Marc Blank } 48470edcf05387df33f4761b766add6b80999e425e9Marc Blank } 48570edcf05387df33f4761b766add6b80999e425e9Marc Blank } finally { 48670edcf05387df33f4761b766add6b80999e425e9Marc Blank c.close(); 48770edcf05387df33f4761b766add6b80999e425e9Marc Blank } 48870edcf05387df33f4761b766add6b80999e425e9Marc Blank } 48970edcf05387df33f4761b766add6b80999e425e9Marc Blank 4903aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon private static void moveCalendarData(final ContentResolver resolver, final String name, 4913aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final String oldType, final String newType) { 4923aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final Uri oldCalendars = Calendars.CONTENT_URI.buildUpon() 4933aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") 4943aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .appendQueryParameter(Calendars.ACCOUNT_NAME, name) 4953aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .appendQueryParameter(Calendars.ACCOUNT_TYPE, oldType) 4963aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .build(); 4973aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon 4983aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon // Update this calendar to have the new account type. 4993aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final ContentValues values = new ContentValues(); 5003aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon values.put(CalendarContract.Calendars.ACCOUNT_TYPE, newType); 5013aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon resolver.update(oldCalendars, values, 5023aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon Calendars.ACCOUNT_NAME + "=? AND " + Calendars.ACCOUNT_TYPE + "=?", 5033aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon new String[] {name, oldType}); 5043aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon } 5053aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon 5063aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon private static void moveContactsData(final ContentResolver resolver, final String name, 5073aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final String oldType, final String newType) { 5083aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final Uri oldContacts = RawContacts.CONTENT_URI.buildUpon() 5093aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") 5103aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .appendQueryParameter(RawContacts.ACCOUNT_NAME, name) 5113aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .appendQueryParameter(RawContacts.ACCOUNT_TYPE, oldType) 5123aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon .build(); 5133aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon 5143aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon // Update this calendar to have the new account type. 5153aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon final ContentValues values = new ContentValues(); 5163aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon values.put(CalendarContract.Calendars.ACCOUNT_TYPE, newType); 5173aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon resolver.update(oldContacts, values, null, null); 5183aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon } 5193aad3fcb8bb916c989fe67cfbf527eb0df6fc6d1Martin Hibdon 5203a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler private static final Configuration sOldConfiguration = new Configuration(); 5213a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler private static Map<String, EmailServiceInfo> sServiceMap = null; 5223a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler private static final Object sServiceMapLock = new Object(); 5233a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler 524c18f8f615f134a2b391d06e2d8d49434a8bb94e5Makoto Onuki /** 525f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * Parse services.xml file to find our available email services 52691237e9dcb0a948f17488b464edabcea0f259d31Makoto Onuki */ 5273a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler private static Map<String, EmailServiceInfo> getServiceMap(final Context context) { 5283a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler synchronized (sServiceMapLock) { 5293a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler /** 5303a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler * We cache localized strings here, so make sure to regenerate the service map if 5313a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler * the locale changes 5323a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler */ 5333a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler if (sServiceMap == null) { 5343a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler sOldConfiguration.setTo(context.getResources().getConfiguration()); 5353a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } 536b5eed31d1bdfcb8e8b316c9c49331295718001bdYu Ping Hu 5373a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final int delta = 5383a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler sOldConfiguration.updateFrom(context.getResources().getConfiguration()); 539b5eed31d1bdfcb8e8b316c9c49331295718001bdYu Ping Hu 5403a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler if (sServiceMap != null 5413a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler && !Configuration.needNewResources(delta, ActivityInfo.CONFIG_LOCALE)) { 5423a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler return sServiceMap; 5433a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } 5443a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler 5453a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final ImmutableMap.Builder<String, EmailServiceInfo> builder = ImmutableMap.builder(); 5460397e7fb233bbf76f7ea30ab3e447f74d7c6bcceAnthony Lee if (!context.getResources().getBoolean(R.bool.enable_services)) { 5470397e7fb233bbf76f7ea30ab3e447f74d7c6bcceAnthony Lee // Return an empty map if services have been disabled because this is the Email 5480397e7fb233bbf76f7ea30ab3e447f74d7c6bcceAnthony Lee // Tombstone app. 5490397e7fb233bbf76f7ea30ab3e447f74d7c6bcceAnthony Lee sServiceMap = builder.build(); 5500397e7fb233bbf76f7ea30ab3e447f74d7c6bcceAnthony Lee return sServiceMap; 5510397e7fb233bbf76f7ea30ab3e447f74d7c6bcceAnthony Lee } 5523a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler 5533a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler try { 5543a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final Resources res = context.getResources(); 5553a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final XmlResourceParser xml = res.getXml(R.xml.services); 5563a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler int xmlEventType; 5573a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler // walk through senders.xml file. 5583a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) { 5593a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler if (xmlEventType == XmlResourceParser.START_TAG && 5603a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler "emailservice".equals(xml.getName())) { 5613a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final EmailServiceInfo info = new EmailServiceInfo(); 5623a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final TypedArray ta = 5633a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler res.obtainAttributes(xml, R.styleable.EmailServiceInfo); 5643a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.protocol = ta.getString(R.styleable.EmailServiceInfo_protocol); 5653a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.accountType = ta.getString(R.styleable.EmailServiceInfo_accountType); 5663a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.name = ta.getString(R.styleable.EmailServiceInfo_name); 5673a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.hide = ta.getBoolean(R.styleable.EmailServiceInfo_hide, false); 5683a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler final String klass = 5693a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getString(R.styleable.EmailServiceInfo_serviceClass); 5703a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.intentAction = ta.getString(R.styleable.EmailServiceInfo_intent); 5713a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.intentPackage = 5723a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getString(R.styleable.EmailServiceInfo_intentPackage); 5733a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.defaultSsl = 5743a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_defaultSsl, false); 5753a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.port = ta.getInteger(R.styleable.EmailServiceInfo_port, 0); 5763a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.portSsl = ta.getInteger(R.styleable.EmailServiceInfo_portSsl, 0); 5773a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerTls = ta.getBoolean(R.styleable.EmailServiceInfo_offerTls, false); 5783a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerCerts = 5793a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_offerCerts, false); 5809195a1202483053606f43e871915a5405e955306Martin Hibdon info.offerOAuth = 5819195a1202483053606f43e871915a5405e955306Martin Hibdon ta.getBoolean(R.styleable.EmailServiceInfo_offerOAuth, false); 5823a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerLocalDeletes = 5833a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_offerLocalDeletes, false); 5843a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.defaultLocalDeletes = 5853a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getInteger(R.styleable.EmailServiceInfo_defaultLocalDeletes, 5863a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler Account.DELETE_POLICY_ON_DELETE); 5873a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerPrefix = 5883a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_offerPrefix, false); 5893a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.usesSmtp = ta.getBoolean(R.styleable.EmailServiceInfo_usesSmtp, false); 5903a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.usesAutodiscover = 5913a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_usesAutodiscover, false); 5923a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerLookback = 5933a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_offerLookback, false); 5943a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.defaultLookback = 5953a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getInteger(R.styleable.EmailServiceInfo_defaultLookback, 5963a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler SyncWindow.SYNC_WINDOW_3_DAYS); 5973a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.syncChanges = 5983a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_syncChanges, false); 5993a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.syncContacts = 6003a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_syncContacts, false); 6013a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.syncCalendar = 6023a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_syncCalendar, false); 6033a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerAttachmentPreload = 6043a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_offerAttachmentPreload, 6053a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler false); 6063a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.syncIntervalStrings = 6073a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervalStrings); 6083a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.syncIntervals = 6093a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervals); 6103a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.defaultSyncInterval = 6113a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getInteger(R.styleable.EmailServiceInfo_defaultSyncInterval, 15); 6123a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.inferPrefix = ta.getString(R.styleable.EmailServiceInfo_inferPrefix); 6133a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.offerLoadMore = 6143a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_offerLoadMore, false); 615ae46818a1925cc22fe20ee26ffee8779561a903bAlon Albert info.offerMoveTo = 616ae46818a1925cc22fe20ee26ffee8779561a903bAlon Albert ta.getBoolean(R.styleable.EmailServiceInfo_offerMoveTo, false); 6173a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.requiresSetup = 6183a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_requiresSetup, false); 619751da261722f6b8964c9a4f4b198aeb730addb50Tony Mantler info.isGmailStub = 620751da261722f6b8964c9a4f4b198aeb730addb50Tony Mantler ta.getBoolean(R.styleable.EmailServiceInfo_isGmailStub, false); 6213a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler 6223a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler // Must have either "class" (local) or "intent" (remote) 6233a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler if (klass != null) { 6243a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler try { 6253a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler // noinspection unchecked 6263a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler info.klass = (Class<? extends Service>) Class.forName(klass); 6273a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } catch (ClassNotFoundException e) { 6283a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler throw new IllegalStateException( 6293a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler "Class not found in service descriptor: " + klass); 6303a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } 6313a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } 632751da261722f6b8964c9a4f4b198aeb730addb50Tony Mantler if (info.klass == null && 633751da261722f6b8964c9a4f4b198aeb730addb50Tony Mantler info.intentAction == null && 634751da261722f6b8964c9a4f4b198aeb730addb50Tony Mantler !info.isGmailStub) { 635f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank throw new IllegalStateException( 6363a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler "No class or intent action specified in service descriptor"); 637f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 6383a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler if (info.klass != null && info.intentAction != null) { 6393a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler throw new IllegalStateException( 6403a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler "Both class and intent action specified in service descriptor"); 6413a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } 6423a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler builder.put(info.protocol, info); 643f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 644f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 6453a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } catch (XmlPullParserException e) { 6463a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler // ignore 6473a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler } catch (IOException e) { 6483a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler // ignore 649f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 6503a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler sServiceMap = builder.build(); 6513a8c86b18265eb3786bf32b5c043b5942ddb4e45Tony Mantler return sServiceMap; 65203cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 653f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank } 65453b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler 65553b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler /** 65653b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler * Resolves a service name into a protocol name, or null if ambiguous 65753b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler * @param context for loading service map 65853b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler * @param accountType sync adapter service name 65953b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler * @return protocol name or null 66053b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler */ 6614c865846856cd7530fb51e244a9971a3d5e1fcd8Tony Mantler public static @Nullable String getProtocolFromAccountType(final Context context, 66253b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler final String accountType) { 6634c865846856cd7530fb51e244a9971a3d5e1fcd8Tony Mantler if (TextUtils.isEmpty(accountType)) { 6644c865846856cd7530fb51e244a9971a3d5e1fcd8Tony Mantler return null; 6654c865846856cd7530fb51e244a9971a3d5e1fcd8Tony Mantler } 66653b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler final Map <String, EmailServiceInfo> serviceInfoMap = getServiceMap(context); 66753b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler String protocol = null; 66853b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler for (final EmailServiceInfo info : serviceInfoMap.values()) { 66953b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler if (TextUtils.equals(accountType, info.accountType)) { 67053b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler if (!TextUtils.isEmpty(protocol) && !TextUtils.equals(protocol, info.protocol)) { 67153b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler // More than one protocol matches 67253b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler return null; 67353b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler } 67453b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler protocol = info.protocol; 67553b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler } 67653b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler } 67753b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler return protocol; 67853b64eee54cdb74dc325089b8362a6ff4811759eTony Mantler } 67903cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 680e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank private static Uri asCalendarSyncAdapter(Uri uri, String account, String accountType) { 681e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank return uri.buildUpon().appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") 682e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank .appendQueryParameter(Calendars.ACCOUNT_NAME, account) 683e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); 684e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank } 685e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank 686f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank /** 687f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank * A no-op service that can be returned for non-existent/null protocols 688f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank */ 689f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank class NullService implements IEmailService { 690f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 691f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public IBinder asBinder() { 692f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank return null; 69303cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 69403cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 695f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 6961d8fd9c05449863ac6a151a6db87c267c4f55ac2Martin Hibdon public Bundle validate(HostAuthCompat hostauth) throws RemoteException { 697f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank return null; 69803cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 69903cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 700f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 70170cb2878d72ce1c1775ac0426ff82698a5e59377Anthony Lee public void loadAttachment(final IEmailServiceCallback cb, final long accountId, 70270cb2878d72ce1c1775ac0426ff82698a5e59377Anthony Lee final long attachmentId, final boolean background) throws RemoteException { 70303cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 70403cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 705f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 706fb2a3a2f77f954265beaa92b87774006e2d7c185Martin Hibdon public void updateFolderList(long accountId) throws RemoteException {} 70703cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 708f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 709fb2a3a2f77f954265beaa92b87774006e2d7c185Martin Hibdon public void setLogging(int flags) throws RemoteException { 71003cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 71103cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 712f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 713f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public Bundle autoDiscover(String userName, String password) throws RemoteException { 714f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank return null; 71503cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 71603cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 717f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 718f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public void sendMeetingResponse(long messageId, int response) throws RemoteException { 71903cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 72003cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 721f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 7227afbeee47e1a82680c815f2fb8cfdba32d6b0b84Martin Hibdon public void deleteExternalAccountPIMData(final String emailAddress) throws RemoteException { 723c5f5a14ae9095f76d8e8c411cfd8f8e0e8970aa2Martin Hibdon } 724c5f5a14ae9095f76d8e8c411cfd8f8e0e8970aa2Martin Hibdon 725c5f5a14ae9095f76d8e8c411cfd8f8e0e8970aa2Martin Hibdon @Override 726f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public int searchMessages(long accountId, SearchParams params, long destMailboxId) 727f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank throws RemoteException { 72803cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank return 0; 72903cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 73003cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank 731f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank @Override 732f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank public void sendMail(long accountId) throws RemoteException { 73303cd72805dab0379ed255d151f1c17cc60655fc3Marc Blank } 734701134953e4591bf2cca020838558a97eab570a1Yu Ping Hu 735701134953e4591bf2cca020838558a97eab570a1Yu Ping Hu @Override 736701134953e4591bf2cca020838558a97eab570a1Yu Ping Hu public void pushModify(long accountId) throws RemoteException { 737701134953e4591bf2cca020838558a97eab570a1Yu Ping Hu } 7388103f960d0c0469d67652afd616e9924687aa139Yu Ping Hu 7398103f960d0c0469d67652afd616e9924687aa139Yu Ping Hu @Override 740fb2a3a2f77f954265beaa92b87774006e2d7c185Martin Hibdon public int sync(final long accountId, final Bundle syncExtras) { 741fb2a3a2f77f954265beaa92b87774006e2d7c185Martin Hibdon return EmailServiceStatus.SUCCESS; 7428103f960d0c0469d67652afd616e9924687aa139Yu Ping Hu } 7438103f960d0c0469d67652afd616e9924687aa139Yu Ping Hu 7447afbeee47e1a82680c815f2fb8cfdba32d6b0b84Martin Hibdon public int getApiVersion() { 7457afbeee47e1a82680c815f2fb8cfdba32d6b0b84Martin Hibdon return EmailServiceVersion.CURRENT; 7467afbeee47e1a82680c815f2fb8cfdba32d6b0b84Martin Hibdon } 7479fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki } 74874dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon 749ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee public static void setComponentStatus(final Context context, Class<?> clazz, boolean enabled) { 75074dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon final ComponentName c = new ComponentName(context, clazz.getName()); 75174dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon context.getPackageManager().setComponentEnabledSetting(c, 75274dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 75374dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 75474dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon PackageManager.DONT_KILL_APP); 75574dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon } 75674dc106ae9ff3d3a92425b68ea28ee2a0b258e57Martin Hibdon 757ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee /** 758ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee * This is a helper function that enables the proper Exchange component and disables 759ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee * the other Exchange component ensuring that only one is enabled at a time. 760ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee */ 761ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee public static void enableExchangeComponent(final Context context) { 762ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee if (VendorPolicyLoader.getInstance(context).useAlternateExchangeStrings()) { 763ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee LogUtils.d(LogUtils.TAG, "Enabling alternate EAS authenticator"); 764ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee setComponentStatus(context, EasAuthenticatorServiceAlternate.class, true); 765ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee setComponentStatus(context, EasAuthenticatorService.class, false); 766ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee } else { 767ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee LogUtils.d(LogUtils.TAG, "Enabling EAS authenticator"); 768ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee setComponentStatus(context, EasAuthenticatorService.class, true); 769ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee setComponentStatus(context, 770ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee EasAuthenticatorServiceAlternate.class, false); 771ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee } 772ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee } 773ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee 774ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee public static void disableExchangeComponents(final Context context) { 775ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee LogUtils.d(LogUtils.TAG, "Disabling EAS authenticators"); 776ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee setComponentStatus(context, EasAuthenticatorServiceAlternate.class, false); 777ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee setComponentStatus(context, EasAuthenticatorService.class, false); 778ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee } 779ebe49cfeaf0328aa95f5cb82b731f08d7bae7b09Anthony Lee 7809fe51f632965f5d085ae45a1089c7c97dcec8881Makoto Onuki} 781