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.app.AlarmManager;
     32 import android.app.PendingIntent;
     33 import android.content.Context;
     34 import android.content.Intent;
     35 import android.os.SystemClock;
     36 import android.text.format.Time;
     37 
     38 import com.android.ims.internal.Logger;
     39 
     40 import java.util.ArrayList;
     41 import java.util.List;
     42 
     43 public class PollingTask {
     44     private Logger logger = Logger.getLogger(this.getClass().getName());
     45     private Context mContext = null;
     46 
     47     private static long sMaxId = 0;
     48     public static final String ACTION_POLLING_RETRY_ALARM =
     49             "com.android.service.ims.presence.capability_polling_retry";
     50     private PendingIntent mRetryAlarmIntent = null;
     51 
     52     public long mId;
     53     public int mType;
     54     public List<Contacts.Item> mContacts = new ArrayList<Contacts.Item>();
     55 
     56     private long mTimeUnit;
     57     private int mTotalRetry;
     58     private int mCurrentRetry;
     59     private long mLastUpdateTime;
     60 
     61     private boolean mCancelled = false;
     62     private boolean mCompleted = false;
     63 
     64     public PollingTask(int type, List<Contacts.Item> list) {
     65         mId = sMaxId++;
     66         mType = type;
     67 
     68         mContacts.clear();
     69         for(int i = 0; i < list.size(); i++) {
     70             Contacts.Item item = list.get(i);
     71             mContacts.add(item);
     72         }
     73 
     74         mCurrentRetry = 0;
     75         mTotalRetry = 5;
     76         mTimeUnit = 1800; // 1800s = 30 minutes
     77         if (CapabilityPolling.ACTION_POLLING_NEW_CONTACTS == mType) {
     78             mTotalRetry = 4;
     79             mTimeUnit = 60; // 60s = 1 minute
     80         }
     81         mLastUpdateTime = 0;
     82     }
     83 
     84     public void execute() {
     85         PollingsQueue queue = PollingsQueue.getInstance(null);
     86         if (queue == null) {
     87             return;
     88         }
     89 
     90         PollingAction action = new PollingAction(queue.getContext(), this);
     91         action.execute();
     92     }
     93 
     94     public void finish(boolean fullUpdated) {
     95         cancelRetryAlarm();
     96 
     97         PollingsQueue queue = PollingsQueue.getInstance(null);
     98         if (queue == null) {
     99             return;
    100         }
    101 
    102         mCompleted = fullUpdated ? true : false;
    103         queue.remove(this);
    104     }
    105 
    106     public void retry() {
    107         mCurrentRetry += 1;
    108         logger.print("retry mCurrentRetry=" + mCurrentRetry);
    109         if (mCurrentRetry > mTotalRetry) {
    110             logger.print("Retry finished for task: " + this);
    111             updateTimeStampToCurrent();
    112             finish(false);
    113             return;
    114         }
    115 
    116         if (mCancelled) {
    117             logger.print("Task is cancelled: " + this);
    118             finish(false);
    119             return;
    120         }
    121 
    122         long delay = mTimeUnit;
    123         for (int i = 0; i < mCurrentRetry - 1; i++) {
    124             delay *= 2;
    125         }
    126 
    127         logger.print("retry delay=" + delay);
    128 
    129         scheduleRetry(delay * 1000);
    130     }
    131 
    132     public void cancel() {
    133         mCancelled = true;
    134         logger.print("Cancel this task: " + this);
    135 
    136         if (mRetryAlarmIntent != null) {
    137             cancelRetryAlarm();
    138             finish(false);
    139         }
    140     }
    141 
    142     public void onPreExecute() {
    143         logger.print("onPreExecute(), id = " + mId);
    144         cancelRetryAlarm();
    145     }
    146 
    147     public void onPostExecute(int result) {
    148         logger.print("onPostExecute(), result = " + result);
    149         mLastUpdateTime = System.currentTimeMillis();
    150     }
    151 
    152     private void updateTimeStampToCurrent() {
    153         if (mContext == null) {
    154             return;
    155         }
    156 
    157         EABContactManager contactManager = new EABContactManager(
    158                 mContext.getContentResolver(), mContext.getPackageName());
    159         for (int i = 0; i < mContacts.size(); i++) {
    160             Contacts.Item item = mContacts.get(i);
    161 
    162             String number = item.number();
    163             long current = System.currentTimeMillis();
    164             EABContactManager.Request request = new EABContactManager.Request(number)
    165                     .setLastUpdatedTimeStamp(current);
    166             int result = contactManager.update(request);
    167             if (result <= 0) {
    168                 logger.debug("failed to update timestamp for contact: ");
    169             }
    170         }
    171     }
    172 
    173     private void cancelRetryAlarm() {
    174         if (mRetryAlarmIntent != null) {
    175             if (mContext != null) {
    176                 AlarmManager alarmManager = (AlarmManager)
    177                         mContext.getSystemService(Context.ALARM_SERVICE);
    178                 alarmManager.cancel(mRetryAlarmIntent);
    179             }
    180             mRetryAlarmIntent = null;
    181         }
    182     }
    183 
    184     private void scheduleRetry(long msec) {
    185         logger.print("scheduleRetry msec=" + msec);
    186 
    187         cancelRetryAlarm();
    188 
    189         if (mContext == null) {
    190             PollingsQueue queue = PollingsQueue.getInstance(null);
    191             if (queue != null) {
    192                 mContext = queue.getContext();
    193             }
    194         }
    195 
    196         if (mContext != null) {
    197             Intent intent = new Intent(ACTION_POLLING_RETRY_ALARM);
    198             intent.setClass(mContext, AlarmBroadcastReceiver.class);
    199             intent.putExtra("pollingTaskId", mId);
    200 
    201             mRetryAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent,
    202                     PendingIntent.FLAG_UPDATE_CURRENT);
    203 
    204             AlarmManager alarmManager = (AlarmManager)
    205                     mContext.getSystemService(Context.ALARM_SERVICE);
    206             alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    207                     SystemClock.elapsedRealtime() + msec, mRetryAlarmIntent);
    208         }
    209     }
    210 
    211     private String getTimeString(long time) {
    212         if (time <= 0) {
    213             time = System.currentTimeMillis();
    214         }
    215 
    216         Time tobj = new Time();
    217         tobj.set(time);
    218         return String.format("%s.%s", tobj.format("%m-%d %H:%M:%S"), time % 1000);
    219     }
    220 
    221     public boolean isCompleted() {
    222         return mCompleted;
    223     }
    224 
    225     @Override
    226     public boolean equals(Object o) {
    227         if (this == o) return true;
    228         if (!(o instanceof PollingTask)) return false;
    229 
    230         PollingTask that = (PollingTask)o;
    231         return (this.mId == that.mId) && (this.mType == that.mType);
    232     }
    233 
    234     @Override
    235     public String toString() {
    236         StringBuilder sb = new StringBuilder();
    237         sb.append("PollingTask { ");
    238         sb.append("\nId: " + mId);
    239         sb.append("\nType: " + mType);
    240         sb.append("\nCurrentRetry: " + mCurrentRetry);
    241         sb.append("\nTotalRetry: " + mTotalRetry);
    242         sb.append("\nTimeUnit: " + mTimeUnit);
    243         sb.append("\nLast update time: " + mLastUpdateTime + "(" +
    244                 getTimeString(mLastUpdateTime) + ")");
    245         sb.append("\nContacts: " + mContacts.size());
    246         for (int i = 0; i < mContacts.size(); i++) {
    247             sb.append("\n");
    248             Contacts.Item item = mContacts.get(i);
    249             sb.append("Number " + i + ": " + Logger.hidePhoneNumberPii(item.number()));
    250         }
    251         sb.append("\nCompleted: " + mCompleted);
    252         sb.append(" }");
    253         return sb.toString();
    254     }
    255 }
    256 
    257