• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2008 Esmertec AG.
3  * Copyright (C) 2007-2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.im.app;
19 
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 
26 import android.app.Activity;
27 import android.app.Application;
28 import android.content.ComponentName;
29 import android.content.ContentResolver;
30 import android.content.ContentUris;
31 import android.content.ContentValues;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.ServiceConnection;
35 import android.content.pm.PackageManager;
36 import android.content.pm.PackageManager.NameNotFoundException;
37 import android.content.res.Resources;
38 import android.database.Cursor;
39 import android.net.ConnectivityManager;
40 import android.net.Uri;
41 import android.os.Broadcaster;
42 import android.os.Handler;
43 import android.os.IBinder;
44 import android.os.Message;
45 import android.os.RemoteException;
46 import android.util.Log;
47 
48 import com.android.im.IConnectionCreationListener;
49 import com.android.im.IImConnection;
50 import com.android.im.IRemoteImService;
51 import com.android.im.R;
52 import com.android.im.app.adapter.ConnectionListenerAdapter;
53 import com.android.im.engine.ImConnection;
54 import com.android.im.engine.ImErrorInfo;
55 import com.android.im.plugin.BrandingResourceIDs;
56 import com.android.im.plugin.ImPlugin;
57 import com.android.im.plugin.ImPluginInfo;
58 import com.android.im.provider.Imps;
59 import com.android.im.service.ImServiceConstants;
60 
61 public class ImApp extends Application {
62     public static final String LOG_TAG = "ImApp";
63 
64     public static final String EXTRA_INTENT_SEND_TO_USER = "Send2_U";
65     public static final String EXTRA_INTENT_PASSWORD = "password";
66 
67     public static final String IMPS_CATEGORY = "com.android.im.IMPS_CATEGORY";
68 
69     private static ImApp sImApp;
70 
71     IRemoteImService mImService;
72 
73     HashMap<Long, IImConnection> mConnections;
74     MyConnListener mConnectionListener;
75     HashMap<Long, ProviderDef> mProviders;
76 
77     Broadcaster mBroadcaster;
78 
79     /** A queue of messages that are waiting to be sent when service is connected.*/
80     ArrayList<Message> mQueue = new ArrayList<Message>();
81 
82     /** A flag indicates that we have called to start the service.*/
83     private boolean mServiceStarted;
84     private Context mApplicationContext;
85     private Resources mPrivateResources;
86 
87     private HashMap<String, BrandingResources> mBrandingResources;
88     private BrandingResources mDefaultBrandingResources;
89 
90     public static final int EVENT_SERVICE_CONNECTED = 100;
91     public static final int EVENT_CONNECTION_CREATED = 150;
92     public static final int EVENT_CONNECTION_LOGGING_IN = 200;
93     public static final int EVENT_CONNECTION_LOGGED_IN = 201;
94     public static final int EVENT_CONNECTION_LOGGING_OUT = 202;
95     public static final int EVENT_CONNECTION_DISCONNECTED = 203;
96     public static final int EVENT_CONNECTION_SUSPENDED = 204;
97     public static final int EVENT_USER_PRESENCE_UPDATED = 300;
98     public static final int EVENT_UPDATE_USER_PRESENCE_ERROR = 301;
99 
100     private static final String[] PROVIDER_PROJECTION = {
101         Imps.Provider._ID,
102         Imps.Provider.NAME,
103         Imps.Provider.FULLNAME,
104         Imps.Provider.SIGNUP_URL,
105     };
106 
107     private static final String[] ACCOUNT_PROJECTION = {
108         Imps.Account._ID,
109         Imps.Account.PROVIDER,
110         Imps.Account.NAME,
111         Imps.Account.USERNAME,
112         Imps.Account.PASSWORD,
113     };
114 
log(String log)115     static final void log(String log) {
116         Log.d(LOG_TAG, log);
117     }
118 
getApplication(Activity activity)119     public static ImApp getApplication(Activity activity) {
120         // TODO should this be synchronized?
121         if (sImApp == null) {
122             initialize(activity);
123         }
124 
125         return sImApp;
126     }
127 
128     /**
129      * Initialize performs the manual ImApp instantiation and initialization. When the
130      * ImApp is started first in the process, the ImApp public constructor should be called,
131      * and sImApp initialized. So calling initialize() later should have no effect. However,
132      * if another application runs in the same process and is started first, the ImApp
133      * application object won't be instantiated, and we need to call initialize() manually to
134      * instantiate and initialize it.
135      */
initialize(Activity activity)136     private static void initialize(Activity activity) {
137         // construct the TalkApp manually and call onCreate().
138         sImApp = new ImApp();
139         sImApp.mApplicationContext = activity.getApplication();
140         sImApp.mPrivateResources = activity.getResources();
141         sImApp.onCreate();
142     }
143 
144     @Override
getResources()145     public Resources getResources() {
146         if (mApplicationContext == this) {
147             return super.getResources();
148         }
149 
150         return mPrivateResources;
151     }
152 
153     @Override
getContentResolver()154     public ContentResolver getContentResolver() {
155         if (mApplicationContext == this) {
156             return super.getContentResolver();
157         }
158 
159         return mApplicationContext.getContentResolver();
160     }
161 
ImApp()162     public ImApp() {
163         super();
164         mConnections = new HashMap<Long, IImConnection>();
165         mApplicationContext = this;
166         sImApp = this;
167     }
168 
169     @Override
onCreate()170     public void onCreate() {
171         super.onCreate();
172         mBroadcaster = new Broadcaster();
173         loadDefaultBrandingRes();
174     }
175 
176     @Override
onTerminate()177     public void onTerminate() {
178         stopImServiceIfInactive();
179         if (mImService != null) {
180             try {
181                 mImService.removeConnectionCreatedListener(mConnCreationListener);
182             } catch (RemoteException e) {
183                 Log.w(LOG_TAG, "failed to remove ConnectionCreatedListener");
184             }
185         }
186 
187         super.onTerminate();
188     }
189 
startImServiceIfNeed()190     public synchronized void startImServiceIfNeed() {
191         if(!mServiceStarted) {
192             if(Log.isLoggable(LOG_TAG, Log.DEBUG)) log("start ImService");
193 
194             Intent serviceIntent = new Intent();
195             serviceIntent.setComponent(ImServiceConstants.IM_SERVICE_COMPONENT);
196             mApplicationContext.startService(serviceIntent);
197             mApplicationContext.bindService(serviceIntent, mImServiceConn, Context.BIND_AUTO_CREATE);
198             mServiceStarted = true;
199 
200             mConnectionListener = new MyConnListener(new Handler());
201         }
202     }
203 
stopImServiceIfInactive()204     public synchronized void stopImServiceIfInactive() {
205         boolean hasActiveConnection = true;
206         synchronized (mConnections) {
207             hasActiveConnection = !mConnections.isEmpty();
208         }
209 
210         if (!hasActiveConnection && mServiceStarted) {
211             if (Log.isLoggable(LOG_TAG, Log.DEBUG))
212                 log("stop ImService because there's no active connections");
213 
214             if(mImService != null) {
215                 mApplicationContext.unbindService(mImServiceConn);
216                 mImService = null;
217             }
218             Intent intent = new Intent();
219             intent.setComponent(ImServiceConstants.IM_SERVICE_COMPONENT);
220             mApplicationContext.stopService(intent);
221             mServiceStarted = false;
222         }
223     }
224 
225     private ServiceConnection mImServiceConn = new ServiceConnection() {
226         public void onServiceConnected(ComponentName className, IBinder service) {
227             if(Log.isLoggable(LOG_TAG, Log.DEBUG))
228                 log("service connected");
229 
230             mImService = IRemoteImService.Stub.asInterface(service);
231             fetchActiveConnections();
232 
233             synchronized (mQueue) {
234                 for (Message msg : mQueue) {
235                     msg.sendToTarget();
236                 }
237                 mQueue.clear();
238             }
239             Message msg = Message.obtain(null, EVENT_SERVICE_CONNECTED);
240             mBroadcaster.broadcast(msg);
241         }
242 
243         public void onServiceDisconnected(ComponentName className) {
244             if(Log.isLoggable(LOG_TAG, Log.DEBUG))
245                 log("service disconnected");
246 
247             mConnections.clear();
248             mImService = null;
249         }
250     };
251 
serviceConnected()252     public boolean serviceConnected() {
253         return mImService != null;
254     }
255 
isBackgroundDataEnabled()256     public boolean isBackgroundDataEnabled() {
257         ConnectivityManager manager =
258                 (ConnectivityManager) mApplicationContext.getSystemService(CONNECTIVITY_SERVICE);
259         return manager.getBackgroundDataSetting();
260     }
261 
insertOrUpdateAccount(ContentResolver cr, long providerId, String userName, String pw)262     public static long insertOrUpdateAccount(ContentResolver cr,
263             long providerId, String userName, String pw) {
264         String selection = Imps.Account.PROVIDER + "=? AND " + Imps.Account.USERNAME + "=?";
265         String[] selectionArgs = {Long.toString(providerId), userName };
266 
267         Cursor c = cr.query(Imps.Account.CONTENT_URI, ACCOUNT_PROJECTION,
268                 selection, selectionArgs, null);
269         if (c != null && c.moveToFirst()) {
270             // Update the password
271             c.updateString(c.getColumnIndexOrThrow(Imps.Account.PASSWORD), pw);
272             c.commitUpdates();
273 
274             long id = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID));
275             c.close();
276             return id;
277         } else {
278             ContentValues values = new ContentValues(4);
279             values.put(Imps.Account.PROVIDER, providerId);
280             values.put(Imps.Account.NAME, userName);
281             values.put(Imps.Account.USERNAME, userName);
282             values.put(Imps.Account.PASSWORD, pw);
283 
284             Uri result = cr.insert(Imps.Account.CONTENT_URI, values);
285             return ContentUris.parseId(result);
286         }
287     }
288 
loadImProviderSettings()289     private void loadImProviderSettings() {
290         if (mProviders != null) {
291             return;
292         }
293 
294         mProviders = new HashMap<Long, ProviderDef>();
295         ContentResolver cr = getContentResolver();
296 
297         String selectionArgs[] = new String[1];
298         selectionArgs[0] = ImApp.IMPS_CATEGORY;
299 
300         Cursor c = cr.query(Imps.Provider.CONTENT_URI, PROVIDER_PROJECTION,
301                 Imps.Provider.CATEGORY+"=?", selectionArgs, null);
302         if (c == null) {
303             return;
304         }
305 
306         try {
307             while (c.moveToNext()) {
308                 long id = c.getLong(0);
309                 String providerName = c.getString(1);
310                 String fullName = c.getString(2);
311                 String signUpUrl = c.getString(3);
312 
313                 mProviders.put(id, new ProviderDef(id, providerName, fullName, signUpUrl));
314             }
315         } finally {
316             c.close();
317         }
318     }
319 
loadDefaultBrandingRes()320     private void loadDefaultBrandingRes() {
321         HashMap<Integer, Integer> resMapping = new HashMap<Integer, Integer>();
322 
323         resMapping.put(BrandingResourceIDs.DRAWABLE_LOGO, R.drawable.imlogo_s);
324         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE,
325                 android.R.drawable.presence_online);
326         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY,
327                 android.R.drawable.presence_away);
328         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY,
329                 android.R.drawable.presence_busy);
330         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE,
331                 android.R.drawable.presence_invisible);
332         resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE,
333                 android.R.drawable.presence_offline);
334         resMapping.put(BrandingResourceIDs.DRAWABLE_READ_CHAT,
335                 R.drawable.status_chat);
336         resMapping.put(BrandingResourceIDs.DRAWABLE_UNREAD_CHAT,
337                 R.drawable.status_chat_new);
338         resMapping.put(BrandingResourceIDs.DRAWABLE_BLOCK,
339                 R.drawable.ic_im_block);
340 
341         resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_NAMES,
342                 R.array.default_smiley_names);
343         resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS,
344                 R.array.default_smiley_texts);
345 
346         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AVAILABLE,
347                 R.string.presence_available);
348         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_BUSY,
349                 R.string.presence_busy);
350         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AWAY,
351                 R.string.presence_away);
352         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_IDLE,
353                 R.string.presence_idle);
354         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_OFFLINE,
355                 R.string.presence_offline);
356         resMapping.put(BrandingResourceIDs.STRING_PRESENCE_INVISIBLE,
357                 R.string.presence_invisible);
358         resMapping.put(BrandingResourceIDs.STRING_LABEL_USERNAME,
359                 R.string.label_username);
360         resMapping.put(BrandingResourceIDs.STRING_ONGOING_CONVERSATION,
361                 R.string.ongoing_conversation);
362         resMapping.put(BrandingResourceIDs.STRING_ADD_CONTACT_TITLE,
363                 R.string.add_contact_title);
364         resMapping.put(BrandingResourceIDs.STRING_LABEL_INPUT_CONTACT,
365                 R.string.input_contact_label);
366         resMapping.put(BrandingResourceIDs.STRING_BUTTON_ADD_CONTACT,
367                 R.string.invite_label);
368         resMapping.put(BrandingResourceIDs.STRING_CONTACT_INFO_TITLE,
369                 R.string.contact_profile_title);
370 
371         resMapping.put(BrandingResourceIDs.STRING_MENU_ADD_CONTACT,
372                 R.string.menu_add_contact);
373         resMapping.put(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT,
374                 R.string.menu_block_contact);
375         resMapping.put(BrandingResourceIDs.STRING_MENU_CONTACT_LIST,
376                 R.string.menu_view_contact_list);
377         resMapping.put(BrandingResourceIDs.STRING_MENU_DELETE_CONTACT,
378                 R.string.menu_remove_contact);
379         resMapping.put(BrandingResourceIDs.STRING_MENU_END_CHAT,
380                 R.string.menu_end_conversation);
381         resMapping.put(BrandingResourceIDs.STRING_MENU_INSERT_SMILEY,
382                 R.string.menu_insert_smiley);
383         resMapping.put(BrandingResourceIDs.STRING_MENU_START_CHAT,
384                 R.string.menu_start_chat);
385         resMapping.put(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE,
386                 R.string.menu_view_profile);
387         resMapping.put(BrandingResourceIDs.STRING_MENU_SWITCH_CHATS,
388                 R.string.menu_switch_chats);
389 
390         resMapping.put(BrandingResourceIDs.STRING_TOAST_CHECK_AUTO_SIGN_IN,
391                 R.string.check_auto_sign_in);
392         resMapping.put(BrandingResourceIDs.STRING_LABEL_SIGN_UP,
393                 R.string.sign_up);
394 
395         mDefaultBrandingResources = new BrandingResources(this, resMapping,
396                 null /* default res */);
397     }
398 
loadThirdPartyResources()399     private void loadThirdPartyResources() {
400         ImPluginHelper helper = ImPluginHelper.getInstance(this);
401         helper.loadAvaiablePlugins();
402         ArrayList<ImPlugin> pluginList = helper.getPluginObjects();
403         ArrayList<ImPluginInfo> infoList = helper.getPluginsInfo();
404         int N = pluginList.size();
405         PackageManager pm = getPackageManager();
406         for (int i = 0; i < N; i++) {
407             ImPlugin plugin = pluginList.get(i);
408             ImPluginInfo pluginInfo = infoList.get(i);
409 
410             try {
411                 Resources packageRes = pm.getResourcesForApplication(pluginInfo.mPackageName);
412 
413                 Map<Integer, Integer> resMap = plugin.getResourceMap();
414                 int[] smileyIcons = plugin.getSmileyIconIds();
415 
416                 BrandingResources res = new BrandingResources(packageRes, resMap,
417                         smileyIcons, mDefaultBrandingResources);
418                 mBrandingResources.put(pluginInfo.mProviderName, res);
419             } catch (NameNotFoundException e) {
420                 Log.e(LOG_TAG, "Failed to load third party resources.", e);
421             }
422         }
423     }
424 
getProviderId(String name)425     public long getProviderId(String name) {
426         loadImProviderSettings();
427         for (ProviderDef provider: mProviders.values()) {
428             if(provider.mName.equals(name)) {
429                 return provider.mId;
430             }
431         }
432         return -1;
433     }
434 
getProvider(long id)435     public ProviderDef getProvider(long id) {
436         loadImProviderSettings();
437         return mProviders.get(id);
438     }
439 
getProviders()440     public List<ProviderDef> getProviders() {
441         loadImProviderSettings();
442         ArrayList<ProviderDef> result = new ArrayList<ProviderDef>();
443         result.addAll(mProviders.values());
444         return result;
445     }
446 
getBrandingResource(long providerId)447     public BrandingResources getBrandingResource(long providerId) {
448         ProviderDef provider = getProvider(providerId);
449         if (provider == null) {
450             return mDefaultBrandingResources;
451         }
452         if (mBrandingResources == null) {
453             mBrandingResources = new HashMap<String, BrandingResources>();
454             loadThirdPartyResources();
455         }
456         BrandingResources res = mBrandingResources.get(provider.mName);
457         return res == null ? mDefaultBrandingResources : res;
458     }
459 
createConnection(long providerId)460     public IImConnection createConnection(long providerId) throws RemoteException {
461         if (mImService == null) {
462             // Service hasn't been connected or has died.
463             return null;
464         }
465         IImConnection conn = getConnection(providerId);
466         if (conn == null) {
467             conn = mImService.createConnection(providerId);
468         }
469         return conn;
470     }
471 
getConnection(long providerId)472     IImConnection getConnection(long providerId) {
473         synchronized (mConnections) {
474             return mConnections.get(providerId);
475         }
476     }
477 
getConnectionByAccount(long accountId)478     public IImConnection getConnectionByAccount(long accountId) {
479         synchronized (mConnections) {
480             for (IImConnection conn : mConnections.values()) {
481                 try {
482                     if (conn.getAccountId() == accountId) {
483                         return conn;
484                     }
485                 } catch (RemoteException e) {
486                     // No server!
487                 }
488             }
489             return null;
490         }
491     }
492 
getActiveConnections()493     public List<IImConnection> getActiveConnections() {
494         synchronized (mConnections) {
495             ArrayList<IImConnection> result = new ArrayList<IImConnection>();
496             result.addAll(mConnections.values());
497             return result;
498         }
499     }
500 
callWhenServiceConnected(Handler target, Runnable callback)501     public void callWhenServiceConnected(Handler target, Runnable callback) {
502         Message msg = Message.obtain(target, callback);
503         if (serviceConnected()) {
504             msg.sendToTarget();
505         } else {
506             startImServiceIfNeed();
507             synchronized (mQueue) {
508                 mQueue.add(msg);
509             }
510         }
511     }
512 
removePendingCall(Handler target)513     public void removePendingCall(Handler target) {
514         synchronized (mQueue) {
515            Iterator<Message> iter = mQueue.iterator();
516            while (iter.hasNext()) {
517                Message msg = iter.next();
518                if (msg.getTarget() == target) {
519                    iter.remove();
520                }
521            }
522        }
523    }
524 
registerForBroadcastEvent(int what, Handler target)525     public void registerForBroadcastEvent(int what, Handler target) {
526         mBroadcaster.request(what, target, what);
527     }
528 
unregisterForBroadcastEvent(int what, Handler target)529     public void unregisterForBroadcastEvent(int what, Handler target) {
530         mBroadcaster.cancelRequest(what, target, what);
531     }
532 
registerForConnEvents(Handler handler)533     public void registerForConnEvents(Handler handler) {
534         mBroadcaster.request(EVENT_CONNECTION_CREATED, handler,
535                 EVENT_CONNECTION_CREATED);
536         mBroadcaster.request(EVENT_CONNECTION_LOGGING_IN, handler,
537                 EVENT_CONNECTION_LOGGING_IN);
538         mBroadcaster.request(EVENT_CONNECTION_LOGGED_IN, handler,
539                 EVENT_CONNECTION_LOGGED_IN);
540         mBroadcaster.request(EVENT_CONNECTION_LOGGING_OUT, handler,
541                 EVENT_CONNECTION_LOGGING_OUT);
542         mBroadcaster.request(EVENT_CONNECTION_SUSPENDED, handler,
543                 EVENT_CONNECTION_SUSPENDED);
544         mBroadcaster.request(EVENT_CONNECTION_DISCONNECTED, handler,
545                 EVENT_CONNECTION_DISCONNECTED);
546         mBroadcaster.request(EVENT_USER_PRESENCE_UPDATED, handler,
547                 EVENT_USER_PRESENCE_UPDATED);
548         mBroadcaster.request(EVENT_UPDATE_USER_PRESENCE_ERROR, handler,
549                 EVENT_UPDATE_USER_PRESENCE_ERROR);
550     }
551 
unregisterForConnEvents(Handler handler)552     public void unregisterForConnEvents(Handler handler) {
553         mBroadcaster.cancelRequest(EVENT_CONNECTION_CREATED, handler,
554                 EVENT_CONNECTION_CREATED);
555         mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGING_IN, handler,
556                 EVENT_CONNECTION_LOGGING_IN);
557         mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGED_IN, handler,
558                 EVENT_CONNECTION_LOGGED_IN);
559         mBroadcaster.cancelRequest(EVENT_CONNECTION_LOGGING_OUT, handler,
560                 EVENT_CONNECTION_LOGGING_OUT);
561         mBroadcaster.cancelRequest(EVENT_CONNECTION_SUSPENDED, handler,
562                 EVENT_CONNECTION_SUSPENDED);
563         mBroadcaster.cancelRequest(EVENT_CONNECTION_DISCONNECTED, handler,
564                 EVENT_CONNECTION_DISCONNECTED);
565         mBroadcaster.cancelRequest(EVENT_USER_PRESENCE_UPDATED, handler,
566                 EVENT_USER_PRESENCE_UPDATED);
567         mBroadcaster.cancelRequest(EVENT_UPDATE_USER_PRESENCE_ERROR, handler,
568                 EVENT_UPDATE_USER_PRESENCE_ERROR);
569     }
570 
broadcastConnEvent(int what, long providerId, ImErrorInfo error)571     void broadcastConnEvent(int what, long providerId, ImErrorInfo error) {
572         if(Log.isLoggable(LOG_TAG, Log.DEBUG)){
573             log("broadcasting connection event " + what + ", provider id " + providerId);
574         }
575         android.os.Message msg = android.os.Message.obtain(
576                 null,
577                 what,
578                 (int)(providerId >> 32), (int)providerId,
579                 error);
580         mBroadcaster.broadcast(msg);
581     }
582 
dismissNotifications(long providerId)583     public void dismissNotifications(long providerId) {
584         if (mImService != null) {
585             try {
586                 mImService.dismissNotifications(providerId);
587             } catch (RemoteException e) {
588             }
589         }
590     }
591 
dismissChatNotification(long providerId, String username)592     public void dismissChatNotification(long providerId, String username) {
593         if (mImService != null) {
594             try {
595                 mImService.dismissChatNotification(providerId, username);
596             } catch (RemoteException e) {
597             }
598         }
599     }
600 
fetchActiveConnections()601     private void fetchActiveConnections() {
602           try {
603             // register the listener before fetch so that we won't miss any connection.
604             mImService.addConnectionCreatedListener(mConnCreationListener);
605             synchronized (mConnections) {
606                 for(IBinder binder: (List<IBinder>) mImService.getActiveConnections()) {
607                     IImConnection conn = IImConnection.Stub.asInterface(binder);
608                     long providerId = conn.getProviderId();
609                     if (!mConnections.containsKey(providerId)) {
610                         mConnections.put(providerId, conn);
611                         conn.registerConnectionListener(mConnectionListener);
612                     }
613                 }
614             }
615         } catch (RemoteException e) {
616             Log.e(LOG_TAG, "fetching active connections", e);
617         }
618     }
619 
620     private final IConnectionCreationListener mConnCreationListener
621             = new IConnectionCreationListener.Stub() {
622         public void onConnectionCreated(IImConnection conn)
623                 throws RemoteException {
624             long providerId = conn.getProviderId();
625             synchronized (mConnections) {
626                 if (!mConnections.containsKey(providerId)) {
627                     mConnections.put(providerId, conn);
628                     conn.registerConnectionListener(mConnectionListener);
629                 }
630             }
631             broadcastConnEvent(EVENT_CONNECTION_CREATED, providerId, null);
632         }
633       };
634 
635     private final class MyConnListener extends ConnectionListenerAdapter {
MyConnListener(Handler handler)636         public MyConnListener(Handler handler) {
637             super(handler);
638         }
639 
640         @Override
onConnectionStateChange(IImConnection conn, int state, ImErrorInfo error)641         public void onConnectionStateChange(IImConnection conn, int state,
642                 ImErrorInfo error) {
643             if(Log.isLoggable(LOG_TAG, Log.DEBUG)){
644                 log("onConnectionStateChange(" + state + ", " + error + ")");
645             }
646 
647             try {
648                 int what = -1;
649                 long providerId = conn.getProviderId();
650                 switch (state) {
651                 case ImConnection.LOGGED_IN:
652                     what = EVENT_CONNECTION_LOGGED_IN;
653                     break;
654 
655                 case ImConnection.LOGGING_IN:
656                     what = EVENT_CONNECTION_LOGGING_IN;
657                     break;
658 
659                 case ImConnection.LOGGING_OUT:
660                     what = EVENT_CONNECTION_LOGGING_OUT;
661                     synchronized (mConnections) {
662                         mConnections.remove(providerId);
663                     }
664                     break;
665 
666                 case ImConnection.DISCONNECTED:
667                     what = EVENT_CONNECTION_DISCONNECTED;
668                     synchronized (mConnections) {
669                         mConnections.remove(providerId);
670                     }
671                     // stop the service if there isn't an active connection anymore.
672                     stopImServiceIfInactive();
673                     break;
674 
675                 case ImConnection.SUSPENDED:
676                     what = EVENT_CONNECTION_SUSPENDED;
677                     break;
678                 }
679                 if (what != -1) {
680                     broadcastConnEvent(what, providerId, error);
681                 }
682             } catch (RemoteException e) {
683                 Log.e(LOG_TAG, "onConnectionStateChange", e);
684             }
685         }
686 
687         @Override
onUpdateSelfPresenceError(IImConnection connection, ImErrorInfo error)688         public void onUpdateSelfPresenceError(IImConnection connection,
689                 ImErrorInfo error) {
690             if(Log.isLoggable(LOG_TAG, Log.DEBUG)){
691                 log("onUpdateUserPresenceError(" + error + ")");
692             }
693             try {
694                 long providerId = connection.getProviderId();
695                 broadcastConnEvent(EVENT_UPDATE_USER_PRESENCE_ERROR, providerId,
696                         error);
697             } catch (RemoteException e) {
698                 Log.e(LOG_TAG, "onUpdateUserPresenceError", e);
699             }
700         }
701 
702         @Override
onSelfPresenceUpdated(IImConnection connection)703         public void onSelfPresenceUpdated(IImConnection connection) {
704             if(Log.isLoggable(LOG_TAG, Log.DEBUG)) log("onUserPresenceUpdated");
705 
706             try {
707                 long providerId = connection.getProviderId();
708                 broadcastConnEvent(EVENT_USER_PRESENCE_UPDATED, providerId,
709                         null);
710             } catch (RemoteException e) {
711                 Log.e(LOG_TAG, "onUserPresenceUpdated", e);
712             }
713         }
714     }
715 }
716