EmailServiceUtils.java revision 54b6b8b072100551c1820d679108bd8356a0c8be
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.email.service; 18 19import android.app.Service; 20import android.content.Context; 21import android.content.Intent; 22import android.content.res.Resources; 23import android.content.res.TypedArray; 24import android.content.res.XmlResourceParser; 25import android.os.Bundle; 26import android.os.IBinder; 27import android.os.RemoteException; 28import android.util.Log; 29 30import com.android.email.R; 31import com.android.emailcommon.Api; 32import com.android.emailcommon.Logging; 33import com.android.emailcommon.provider.Account; 34import com.android.emailcommon.provider.HostAuth; 35import com.android.emailcommon.service.EmailServiceProxy; 36import com.android.emailcommon.service.IEmailService; 37import com.android.emailcommon.service.IEmailServiceCallback; 38import com.android.emailcommon.service.SearchParams; 39import com.android.emailcommon.service.SyncWindow; 40 41import org.xmlpull.v1.XmlPullParserException; 42 43import java.io.IOException; 44import java.util.ArrayList; 45import java.util.List; 46 47/** 48 * Utility functions for EmailService support. 49 */ 50public class EmailServiceUtils { 51 private static final ArrayList<EmailServiceInfo> sServiceList = 52 new ArrayList<EmailServiceInfo>(); 53 54 /** 55 * Starts an EmailService by protocol 56 */ 57 public static void startService(Context context, String protocol) { 58 EmailServiceInfo info = getServiceInfo(context, protocol); 59 if (info != null && info.intentAction != null) { 60 context.startService(new Intent(info.intentAction)); 61 } 62 } 63 64 /** 65 * Starts all remote services 66 */ 67 public static void startRemoteServices(Context context) { 68 for (EmailServiceInfo info: getServiceInfoList(context)) { 69 if (info.intentAction != null) { 70 context.startService(new Intent(info.intentAction)); 71 } 72 } 73 } 74 75 /** 76 * Returns whether or not remote services are present on device 77 */ 78 public static boolean areRemoteServicesInstalled(Context context) { 79 for (EmailServiceInfo info: getServiceInfoList(context)) { 80 if (info.intentAction != null) { 81 return true; 82 } 83 } 84 return false; 85 } 86 87 /** 88 * Starts all remote services 89 */ 90 public static void setRemoteServicesLogging(Context context, int debugBits) { 91 for (EmailServiceInfo info: getServiceInfoList(context)) { 92 if (info.intentAction != null) { 93 EmailServiceProxy service = 94 EmailServiceUtils.getService(context, null, info.protocol); 95 if (service != null) { 96 try { 97 service.setLogging(debugBits); 98 } catch (RemoteException e) { 99 // Move along, nothing to see 100 } 101 } 102 } 103 } 104 } 105 106 /** 107 * Determine if the EmailService is available 108 */ 109 public static boolean isServiceAvailable(Context context, String protocol) { 110 EmailServiceInfo info = getServiceInfo(context, protocol); 111 if (info == null) return false; 112 if (info.klass != null) return true; 113 return new EmailServiceProxy(context, info.intentAction, null).test(); 114 } 115 116 /** 117 * For a given account id, return a service proxy if applicable, or null. 118 * 119 * @param accountId the message of interest 120 * @result service proxy, or null if n/a 121 */ 122 public static EmailServiceProxy getServiceForAccount(Context context, 123 IEmailServiceCallback callback, long accountId) { 124 return getService(context, callback, Account.getProtocol(context, accountId)); 125 } 126 127 /** 128 * Holder of service information (currently just name and class/intent); if there is a class 129 * member, this is a (local, i.e. same process) service; otherwise, this is a remote service 130 */ 131 public static class EmailServiceInfo { 132 public String protocol; 133 public String name; 134 public String accountType; 135 Class<? extends Service> klass; 136 String intentAction; 137 public int port; 138 public int portSsl; 139 public boolean defaultSsl; 140 public boolean offerTls; 141 public boolean offerCerts; 142 public boolean usesSmtp; 143 public boolean offerLocalDeletes; 144 public int defaultLocalDeletes; 145 public boolean offerPrefix; 146 public boolean usesAutodiscover; 147 public boolean offerLookback; 148 public int defaultLookback; 149 public boolean syncChanges; 150 public boolean syncContacts; 151 public boolean syncCalendar; 152 public boolean offerAttachmentPreload; 153 public CharSequence[] syncIntervalStrings; 154 public CharSequence[] syncIntervals; 155 public int defaultSyncInterval; 156 157 public String toString() { 158 StringBuilder sb = new StringBuilder("Protocol: "); 159 sb.append(protocol); 160 sb.append(", "); 161 sb.append(klass != null ? "Local" : "Remote"); 162 return sb.toString(); 163 } 164 } 165 166 public static EmailServiceProxy getService(Context context, IEmailServiceCallback callback, 167 String protocol) { 168 // Handle the degenerate case here (account might have been deleted) 169 if (protocol == null) { 170 Log.w(Logging.LOG_TAG, "Returning NullService for " + protocol); 171 return new EmailServiceProxy(context, NullService.class, null); 172 } 173 EmailServiceInfo info = getServiceInfo(context, protocol); 174 if (info.klass != null) { 175 return new EmailServiceProxy(context, info.klass, callback); 176 } else { 177 return new EmailServiceProxy(context, info.intentAction, callback); 178 } 179 } 180 181 public static EmailServiceInfo getServiceInfo(Context context, String protocol) { 182 if (sServiceList.isEmpty()) { 183 findServices(context); 184 } 185 for (EmailServiceInfo info: sServiceList) { 186 if (info.protocol.equals(protocol)) { 187 return info; 188 } 189 } 190 return null; 191 } 192 193 public static List<EmailServiceInfo> getServiceInfoList(Context context) { 194 synchronized(sServiceList) { 195 if (sServiceList.isEmpty()) { 196 findServices(context); 197 } 198 return sServiceList; 199 } 200 } 201 202 /** 203 * Parse services.xml file to find our available email services 204 */ 205 @SuppressWarnings("unchecked") 206 private static void findServices(Context context) { 207 try { 208 Resources res = context.getResources(); 209 XmlResourceParser xml = res.getXml(R.xml.services); 210 int xmlEventType; 211 // walk through senders.xml file. 212 while ((xmlEventType = xml.next()) != XmlResourceParser.END_DOCUMENT) { 213 if (xmlEventType == XmlResourceParser.START_TAG && 214 "emailservice".equals(xml.getName())) { 215 EmailServiceInfo info = new EmailServiceInfo(); 216 TypedArray ta = res.obtainAttributes(xml, R.styleable.EmailServiceInfo); 217 info.protocol = ta.getString(R.styleable.EmailServiceInfo_protocol); 218 info.name = ta.getString(R.styleable.EmailServiceInfo_name); 219 String klass = ta.getString(R.styleable.EmailServiceInfo_serviceClass); 220 info.intentAction = ta.getString(R.styleable.EmailServiceInfo_intent); 221 info.accountType = ta.getString(R.styleable.EmailServiceInfo_accountType); 222 info.defaultSsl = ta.getBoolean(R.styleable.EmailServiceInfo_defaultSsl, false); 223 info.port = ta.getInteger(R.styleable.EmailServiceInfo_port, 0); 224 info.portSsl = ta.getInteger(R.styleable.EmailServiceInfo_portSsl, 0); 225 info.offerTls = ta.getBoolean(R.styleable.EmailServiceInfo_offerTls, false); 226 info.offerCerts = ta.getBoolean(R.styleable.EmailServiceInfo_offerCerts, false); 227 info.offerLocalDeletes = 228 ta.getBoolean(R.styleable.EmailServiceInfo_offerLocalDeletes, false); 229 info.defaultLocalDeletes = 230 ta.getInteger(R.styleable.EmailServiceInfo_defaultLocalDeletes, 231 Account.DELETE_POLICY_ON_DELETE); 232 info.offerPrefix = 233 ta.getBoolean(R.styleable.EmailServiceInfo_offerPrefix, false); 234 info.usesSmtp = ta.getBoolean(R.styleable.EmailServiceInfo_usesSmtp, false); 235 info.usesAutodiscover = 236 ta.getBoolean(R.styleable.EmailServiceInfo_usesAutodiscover, false); 237 info.offerLookback = 238 ta.getBoolean(R.styleable.EmailServiceInfo_offerLookback, false); 239 info.defaultLookback = 240 ta.getInteger(R.styleable.EmailServiceInfo_defaultLookback, 241 SyncWindow.SYNC_WINDOW_3_DAYS); 242 info.syncChanges = 243 ta.getBoolean(R.styleable.EmailServiceInfo_syncChanges, false); 244 info.syncContacts = 245 ta.getBoolean(R.styleable.EmailServiceInfo_syncContacts, false); 246 info.syncCalendar = 247 ta.getBoolean(R.styleable.EmailServiceInfo_syncCalendar, false); 248 info.offerAttachmentPreload = 249 ta.getBoolean(R.styleable.EmailServiceInfo_offerAttachmentPreload, false); 250 info.syncIntervalStrings = 251 ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervalStrings); 252 info.syncIntervals = 253 ta.getTextArray(R.styleable.EmailServiceInfo_syncIntervals); 254 info.defaultSyncInterval = 255 ta.getInteger(R.styleable.EmailServiceInfo_defaultSyncInterval, 15); 256 257 // Must have either "class" (local) or "intent" (remote) 258 if (klass != null) { 259 try { 260 info.klass = (Class<? extends Service>) Class.forName(klass); 261 } catch (ClassNotFoundException e) { 262 throw new IllegalStateException( 263 "Class not found in service descriptor: " + klass); 264 } 265 } 266 if (info.klass == null && info.intentAction == null) { 267 throw new IllegalStateException( 268 "No class or intent action specified in service descriptor"); 269 } 270 if (info.klass != null && info.intentAction != null) { 271 throw new IllegalStateException( 272 "Both class and intent action specified in service descriptor"); 273 } 274 sServiceList.add(info); 275 } 276 } 277 } catch (XmlPullParserException e) { 278 // ignore 279 } catch (IOException e) { 280 // ignore 281 } 282 } 283 284 /** 285 * A no-op service that can be returned for non-existent/null protocols 286 */ 287 class NullService implements IEmailService { 288 @Override 289 public IBinder asBinder() { 290 return null; 291 } 292 293 @Override 294 public Bundle validate(HostAuth hostauth) throws RemoteException { 295 return null; 296 } 297 298 @Override 299 public void startSync(long mailboxId, boolean userRequest) throws RemoteException { 300 } 301 302 @Override 303 public void stopSync(long mailboxId) throws RemoteException { 304 } 305 306 @Override 307 public void loadMore(long messageId) throws RemoteException { 308 } 309 310 @Override 311 public void loadAttachment(long attachmentId, boolean background) throws RemoteException { 312 } 313 314 @Override 315 public void updateFolderList(long accountId) throws RemoteException { 316 } 317 318 @Override 319 public boolean createFolder(long accountId, String name) throws RemoteException { 320 return false; 321 } 322 323 @Override 324 public boolean deleteFolder(long accountId, String name) throws RemoteException { 325 return false; 326 } 327 328 @Override 329 public boolean renameFolder(long accountId, String oldName, String newName) 330 throws RemoteException { 331 return false; 332 } 333 334 @Override 335 public void setCallback(IEmailServiceCallback cb) throws RemoteException { 336 } 337 338 @Override 339 public void setLogging(int on) throws RemoteException { 340 } 341 342 @Override 343 public void hostChanged(long accountId) throws RemoteException { 344 } 345 346 @Override 347 public Bundle autoDiscover(String userName, String password) throws RemoteException { 348 return null; 349 } 350 351 @Override 352 public void sendMeetingResponse(long messageId, int response) throws RemoteException { 353 } 354 355 @Override 356 public void deleteAccountPIMData(long accountId) throws RemoteException { 357 } 358 359 @Override 360 public int getApiLevel() throws RemoteException { 361 return Api.LEVEL; 362 } 363 364 @Override 365 public int searchMessages(long accountId, SearchParams params, long destMailboxId) 366 throws RemoteException { 367 return 0; 368 } 369 370 @Override 371 public void sendMail(long accountId) throws RemoteException { 372 } 373 374 @Override 375 public int getCapabilities(long accountId) throws RemoteException { 376 return 0; 377 } 378 } 379} 380