Home | History | Annotate | Download | only in presence
      1 /*
      2  * Copyright (c) 2015, Motorola Mobility LLC
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *     - Redistributions of source code must retain the above copyright
      8  *       notice, this list of conditions and the following disclaimer.
      9  *     - Redistributions in binary form must reproduce the above copyright
     10  *       notice, this list of conditions and the following disclaimer in the
     11  *       documentation and/or other materials provided with the distribution.
     12  *     - Neither the name of Motorola Mobility nor the
     13  *       names of its contributors may be used to endorse or promote products
     14  *       derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     26  * DAMAGE.
     27  */
     28 
     29 package com.android.service.ims.presence;
     30 
     31 import android.content.Intent;
     32 import android.os.IBinder;
     33 import android.os.RemoteException;
     34 import android.app.Service;
     35 import android.os.SystemProperties;
     36 import android.os.Handler;
     37 import android.os.Looper;
     38 import android.os.Message;
     39 import android.os.HandlerThread;
     40 import android.os.Process;
     41 import java.util.ArrayList;
     42 import android.content.ContentValues;
     43 import android.text.TextUtils;
     44 
     45 import com.android.ims.internal.Logger;
     46 import com.android.ims.RcsManager.ResultCode;
     47 import com.android.ims.RcsPresence;
     48 import com.android.ims.RcsPresenceInfo;
     49 
     50 /**
     51  * This service essentially plays the role of a "worker thread", allowing us to store
     52  * presence information.
     53  */
     54 public class PersistService extends Service {
     55     private Logger logger = Logger.getLogger(this.getClass().getName());
     56 
     57     private static final int MESSAGE_PRESENCE_CHANGED = 1;
     58     private static final int MESSAGE_PUBLISH_STATE_CHANGED = 2;
     59 
     60     private int mVltProvisionErrorCount = 0;
     61     private Looper mServiceLooper = null;
     62     private ServiceHandler mServiceHandler = null;
     63     private EABContactManager mEABContactManager = null;
     64 
     65     @Override
     66     public void onCreate() {
     67         mEABContactManager = new EABContactManager(getContentResolver(), getPackageName());
     68 
     69         // separate thread because the service normally runs in the process's
     70         // main thread, which we don't want to block.
     71         HandlerThread thread = new HandlerThread("PersistServiceThread",
     72                 Process.THREAD_PRIORITY_BACKGROUND);
     73         thread.start();
     74 
     75         mServiceLooper = thread.getLooper();
     76         mServiceHandler = new ServiceHandler(mServiceLooper);
     77     }
     78 
     79     @Override
     80     public int onStartCommand(Intent intent, int flags, int startId) {
     81         if(intent == null) {
     82             return Service.START_NOT_STICKY;
     83         }
     84 
     85         if(RcsPresence.ACTION_PRESENCE_CHANGED.equals(intent.getAction())) {
     86             Message msg = mServiceHandler.obtainMessage(MESSAGE_PRESENCE_CHANGED);
     87             msg.arg1 = startId;
     88             msg.obj = intent;
     89             mServiceHandler.sendMessage(msg);
     90             return Service.START_NOT_STICKY;
     91         } else if(RcsPresence.ACTION_PUBLISH_STATE_CHANGED.equals(intent.getAction())) {
     92             Message msg = mServiceHandler.obtainMessage(MESSAGE_PUBLISH_STATE_CHANGED);
     93             msg.arg1 = startId;
     94             msg.obj = intent;
     95             mServiceHandler.sendMessage(msg);
     96             return Service.START_NOT_STICKY;
     97         } else {
     98             logger.debug("unknown intent=" + intent);
     99         }
    100 
    101         return Service.START_NOT_STICKY;
    102     }
    103 
    104     @Override
    105     public void onDestroy() {
    106         mServiceLooper.quit();
    107     }
    108 
    109     @Override
    110     public IBinder onBind(Intent intent) {
    111         return null;
    112     }
    113 
    114     private final class ServiceHandler extends Handler {
    115         public ServiceHandler(Looper looper) {
    116             super(looper);
    117         }
    118 
    119         /**
    120          * Handler to save the presence information.
    121          */
    122         @Override
    123         public void handleMessage(Message msg) {
    124             super.handleMessage(msg);
    125             logger.print( "Thread=" + Thread.currentThread().getName() + " received "
    126                     + msg);
    127             if(msg == null){
    128                 logger.error("msg=null");
    129                 return;
    130             }
    131 
    132             int serviceId = msg.arg1;
    133             Intent intent = (Intent)msg.obj;
    134             logger.print("handleMessage serviceId: " + serviceId + " intent: " + intent);
    135             switch (msg.what) {
    136                 case MESSAGE_PRESENCE_CHANGED:
    137                     if (intent != null) {
    138                         if (RcsPresence.ACTION_PRESENCE_CHANGED.equals(intent.getAction())) {
    139                             handlePresence(intent);
    140                         } else {
    141                             logger.debug("I don't care about intent: " + intent);
    142                         }
    143                         intent.setComponent(null);
    144                         sendBroadcast(intent);
    145                     }
    146                 break;
    147 
    148                 case MESSAGE_PUBLISH_STATE_CHANGED:
    149                     if (intent != null) {
    150                         if (RcsPresence.ACTION_PUBLISH_STATE_CHANGED.equals(intent.getAction())) {
    151                             int publishState = intent.getIntExtra(RcsPresence.EXTRA_PUBLISH_STATE,
    152                                     RcsPresence.PublishState.PUBLISH_STATE_200_OK);
    153                             handlePublishState(publishState);
    154                         } else {
    155                             logger.debug("I don't care about intent: " + intent);
    156                         }
    157                     }
    158                 break;
    159 
    160                 default:
    161                     logger.debug("unknown message:" + msg);
    162             }
    163         }
    164     }
    165 
    166     private void handlePublishState(int publishState) {
    167         if(publishState == RcsPresence.PublishState.PUBLISH_STATE_VOLTE_PROVISION_ERROR) {
    168             mVltProvisionErrorCount += 1;
    169             if(mVltProvisionErrorCount >= 3){
    170                 if(mEABContactManager != null) {
    171                     mEABContactManager.updateAllCapabilityToUnknown();
    172                     logger.print("updateAllCapabilityToUnknown for publish 403 error");
    173                     Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED);
    174                     sendBroadcast(intent);
    175                 } else {
    176                     logger.error("mEABContactManager is null");
    177                 }
    178             }
    179         } else if(publishState == RcsPresence.PublishState.PUBLISH_STATE_RCS_PROVISION_ERROR){
    180             mVltProvisionErrorCount = 0;
    181             if(mEABContactManager != null) {
    182                 mEABContactManager.updateAllVtCapabilityToUnknown();
    183                 logger.print("updateAllVtCapabilityToUnknown for publish 404 error");
    184                 Intent intent = new Intent(RcsPresence.ACTION_PRESENCE_CHANGED);
    185                 sendBroadcast(intent);
    186             } else {
    187                 logger.error("mEABContactManager is null");
    188             }
    189         } else {
    190             mVltProvisionErrorCount = 0;
    191         }
    192     }
    193 
    194     private void handlePresence(Intent intent) {
    195         if(intent == null) {
    196             return;
    197         }
    198 
    199         // save the presence information.
    200         ArrayList<RcsPresenceInfo> rcsPresenceInfoList = intent.getParcelableArrayListExtra(
    201                 RcsPresence.EXTRA_PRESENCE_INFO_LIST);
    202         boolean updateLastTimestamp = intent.getBooleanExtra("updateLastTimestamp", true);
    203         logger.print("updateLastTimestamp=" + updateLastTimestamp +
    204                 " RcsPresenceInfoList=" + rcsPresenceInfoList);
    205         for(int i=0; i< rcsPresenceInfoList.size(); i++){
    206             RcsPresenceInfo rcsPresenceInfoTmp = rcsPresenceInfoList.get(i);
    207             if((rcsPresenceInfoTmp != null) && !TextUtils.isEmpty(
    208                     rcsPresenceInfoTmp.getContactNumber())){
    209                 mEABContactManager.update(rcsPresenceInfoTmp, updateLastTimestamp);
    210             }
    211         }
    212     }
    213 }
    214 
    215 
    216