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 29package com.android.service.ims.presence; 30 31import java.util.Set; 32import java.util.HashMap; 33import java.util.List; 34import java.util.ArrayList; 35import android.content.Context; 36import android.content.Intent; 37import android.app.PendingIntent; 38import android.content.IntentFilter; 39import android.os.RemoteException; 40import android.app.AlarmManager; 41import android.os.SystemClock; 42 43import com.android.ims.internal.uce.presence.PresCmdStatus; 44 45import com.android.ims.RcsManager.ResultCode; 46import com.android.ims.RcsPresenceInfo; 47import com.android.ims.IRcsPresenceListener; 48 49import com.android.ims.internal.Logger; 50import com.android.service.ims.TaskManager; 51 52/** 53 * PresenceCapabilityTask 54 */ 55public class PresenceCapabilityTask extends PresenceTask{ 56 /* 57 * The logger 58 */ 59 private Logger logger = Logger.getLogger(this.getClass().getName()); 60 61 public static final String ACTION_TASK_TIMEOUT_ALARM = 62 "com.android.service.ims.presence.task.timeout"; 63 64 private Context mContext = null; 65 66 // The result code will be used for retry. 67 public int mResultCode; 68 69 // The alarm manager. 70 static AlarmManager sAlarmManager = null; 71 PendingIntent mAlarmIntent = null; 72 boolean mTimerStarted = false; 73 74 // it will be set to true after got sip response. 75 public boolean mWaitingForNotify; 76 77 // The time when created the task. 78 private long mCreatedTimeStamp; 79 80 private long mTimeout; 81 82 public PresenceCapabilityTask(Context context, int taskId, int cmdId, 83 IRcsPresenceListener listener, String[] contacts, 84 long timeout){ 85 super(taskId, cmdId, listener, contacts); 86 mContext = context; 87 mWaitingForNotify = false; 88 89 mCreatedTimeStamp = System.currentTimeMillis(); 90 mTimeout = timeout; 91 92 if(mTimeout <=0){ 93 // The terminal notification may be received shortly after the time limit of 94 // the subscription due to network delays or retransmissions. 95 // Device shall wait for 3sec after the end of the subscription period in order to 96 // accept such notifications without returning spurious errors (e.g. SIP 481). 97 mTimeout = 36000; 98 } 99 100 if(listener != null){ 101 startTimer(); 102 } //else it will be removed after got sip response. 103 } 104 105 public String toString(){ 106 return super.toString() + 107 " mCreatedTimeStamp=" + mCreatedTimeStamp + 108 " mTimeout=" + mTimeout; 109 } 110 111 private void startTimer(){ 112 if(mContext == null){ 113 logger.error("startTimer mContext is null"); 114 return; 115 } 116 117 Intent intent = new Intent(ACTION_TASK_TIMEOUT_ALARM); 118 intent.setClass(mContext, AlarmBroadcastReceiver.class); 119 intent.putExtra("taskId", mTaskId); 120 PendingIntent mAlarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, 121 PendingIntent.FLAG_ONE_SHOT); 122 123 if(sAlarmManager == null){ 124 sAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 125 } 126 127 long triggerAt = SystemClock.elapsedRealtime() + mTimeout; 128 logger.debug("startTimer taskId=" + mTaskId + " mTimeout=" + mTimeout + 129 " triggerAt=" + triggerAt + " mAlarmIntent=" + mAlarmIntent); 130 sAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAt, mAlarmIntent); 131 mTimerStarted = true; 132 } 133 134 public void cancelTimer(){ 135 if(mTimerStarted){ 136 logger.debug("cancelTimer, taskId=" + mTaskId); 137 if(mAlarmIntent != null && sAlarmManager != null) { 138 sAlarmManager.cancel(mAlarmIntent); 139 } 140 mTimerStarted = false; 141 } 142 } 143 144 public void onTimeout(){ 145 logger.debug("onTimeout, taskId=" + mTaskId); 146 try{ 147 if(mListener != null){ 148 mListener.onTimeout(mTaskId); 149 } 150 }catch (RemoteException e){ 151 logger.error("RemoteException", e); 152 } 153 154 TaskManager.getDefault().removeTask(mTaskId); 155 } 156 157 public void setWaitingForNotify(boolean waitingForNotify){ 158 mWaitingForNotify = waitingForNotify; 159 } 160 161 public boolean isWaitingForNotify(){ 162 return mWaitingForNotify; 163 } 164 165 public void onTerminated(String reason){ 166 if(!mWaitingForNotify){ 167 logger.debug("onTerminated mWaitingForNotify is false. task=" + this); 168 return; 169 } 170 171 cancelTimer(); 172 try{ 173 if(mListener != null){ 174 mListener.onFinish(mTaskId); 175 } 176 }catch (RemoteException e){ 177 logger.error("RemoteException", e); 178 } 179 180 TaskManager.getDefault().removeTask(mTaskId); 181 } 182}; 183 184