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