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.ims; 30 31 import android.content.Context; 32 import android.content.Intent; 33 import android.os.IBinder; 34 import android.os.RemoteException; 35 import android.os.ServiceManager; 36 import android.telephony.Rlog; 37 38 import com.android.ims.internal.IRcsService; 39 import com.android.ims.internal.IRcsPresence; 40 41 import java.util.HashMap; 42 43 /** 44 * Provides APIs for Rcs services, currently it supports presence only. 45 * This class is the starting point for any RCS actions. 46 * You can acquire an instance of it with {@link #getInstance getInstance()}. 47 * 48 * @hide 49 */ 50 public class RcsManager { 51 /** 52 * For accessing the RCS related service. 53 * Internal use only. 54 * 55 * @hide 56 */ 57 private static final String RCS_SERVICE = "rcs"; 58 59 /** 60 * Part of the ACTION_RCS_SERVICE_AVAILABLE and ACTION_RCS_SERVICE_UNAVAILABLE intents. 61 * A long value; the subId corresponding to the RCS service. For MSIM implementation. 62 * 63 * @see #ACTION_RCS_SERVICE_AVAILABLE 64 * @see #ACTION_RCS_SERVICE_UNAVAILABLE 65 */ 66 public static final String EXTRA_SUBID = "android:subid"; 67 68 /** 69 * Action to broadcast when RcsService is available. 70 * 71 * @see #EXTRA_SUBID 72 */ 73 public static final String ACTION_RCS_SERVICE_AVAILABLE = 74 "com.android.ims.ACTION_RCS_SERVICE_AVAILABLE"; 75 76 /** 77 * Action to broadcast when RcsService is unavailable (such as ims is not registered). 78 * 79 * @see #EXTRA_SUBID 80 */ 81 public static final String ACTION_RCS_SERVICE_UNAVAILABLE = 82 "com.android.ims.ACTION_RCS_SERVICE_UNAVAILABLE"; 83 84 /** 85 * Action to broadcast when RcsService is died. 86 * The caller can listen to the intent to clean the pending request. 87 * 88 * It takes the extra parameter subid as well since it depends on OEM implementation for 89 * RcsService. It will not send broadcast for ACTION_RCS_SERVICE_UNAVAILABLE under the case. 90 * 91 * @see #EXTRA_SUBID 92 */ 93 public static final String ACTION_RCS_SERVICE_DIED = 94 "com.android.ims.ACTION_RCS_SERVICE_DIED"; 95 96 ; 97 98 private static final String TAG = "RcsManager"; 99 private static final boolean DBG = true; 100 101 private static HashMap<Integer, RcsManager> sRcsManagerInstances = 102 new HashMap<Integer, RcsManager>(); 103 104 private Context mContext; 105 private int mSubId; 106 private IRcsService mRcsService = null; 107 private RcsServiceDeathRecipient mDeathRecipient = new RcsServiceDeathRecipient(); 108 109 // Interface for presence 110 // TODO: Could add other RCS service such RcsChat, RcsFt later. 111 private RcsPresence mRcsPresence = null; 112 113 /** 114 * Gets a manager instance. 115 * 116 * @param context application context for creating the manager object 117 * @param subId the subscription ID for the RCS Service 118 * @return the manager instance corresponding to the subId 119 */ getInstance(Context context, int subId)120 public static RcsManager getInstance(Context context, int subId) { 121 synchronized (sRcsManagerInstances) { 122 if (sRcsManagerInstances.containsKey(subId)){ 123 return sRcsManagerInstances.get(subId); 124 } 125 126 RcsManager mgr = new RcsManager(context, subId); 127 sRcsManagerInstances.put(subId, mgr); 128 129 return mgr; 130 } 131 } 132 RcsManager(Context context, int subId)133 private RcsManager(Context context, int subId) { 134 mContext = context; 135 mSubId = subId; 136 createRcsService(true); 137 } 138 139 /** 140 * return true if the rcs service is ready for use. 141 */ isRcsServiceAvailable()142 public boolean isRcsServiceAvailable() { 143 if (DBG) Rlog.d(TAG, "call isRcsServiceAvailable ..."); 144 145 boolean ret = false; 146 147 try { 148 checkAndThrowExceptionIfServiceUnavailable(); 149 150 ret = mRcsService.isRcsServiceAvailable(); 151 } catch (RemoteException e) { 152 // return false under the case. 153 Rlog.e(TAG, "isRcsServiceAvailable RemoteException", e); 154 }catch (RcsException e){ 155 // return false under the case. 156 Rlog.e(TAG, "isRcsServiceAvailable RcsException", e); 157 } 158 159 if (DBG) Rlog.d(TAG, "isRcsServiceAvailable ret =" + ret); 160 return ret; 161 } 162 163 /** 164 * Gets the presence interface 165 * 166 * @return the RcsPresence instance. 167 * @throws if getting the RcsPresence interface results in an error. 168 */ getRcsPresenceInterface()169 public RcsPresence getRcsPresenceInterface() throws RcsException { 170 171 if (mRcsPresence == null) { 172 checkAndThrowExceptionIfServiceUnavailable(); 173 174 try { 175 IRcsPresence rcsPresence = mRcsService.getRcsPresenceInterface(); 176 if (rcsPresence == null) { 177 throw new RcsException("getRcsPresenceInterface()", 178 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 179 } 180 mRcsPresence = new RcsPresence(rcsPresence); 181 } catch (RemoteException e) { 182 throw new RcsException("getRcsPresenceInterface()", e, 183 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 184 } 185 } 186 if (DBG) Rlog.d(TAG, "getRcsPresenceInterface(), mRcsPresence= " + mRcsPresence); 187 return mRcsPresence; 188 } 189 190 /** 191 * Binds the RCS service only if the service is not created. 192 */ checkAndThrowExceptionIfServiceUnavailable()193 private void checkAndThrowExceptionIfServiceUnavailable() 194 throws RcsException { 195 if (mRcsService == null) { 196 createRcsService(true); 197 198 if (mRcsService == null) { 199 throw new RcsException("Service is unavailable", 200 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 201 } 202 } 203 } 204 getRcsServiceName(int subId)205 private static String getRcsServiceName(int subId) { 206 // use the same mechanism as IMS_SERVICE? 207 return RCS_SERVICE; 208 } 209 210 /** 211 * Binds the RCS service. 212 */ createRcsService(boolean checkService)213 private void createRcsService(boolean checkService) { 214 if (checkService) { 215 IBinder binder = ServiceManager.checkService(getRcsServiceName(mSubId)); 216 217 if (binder == null) { 218 return; 219 } 220 } 221 222 IBinder b = ServiceManager.getService(getRcsServiceName(mSubId)); 223 224 if (b != null) { 225 try { 226 b.linkToDeath(mDeathRecipient, 0); 227 } catch (RemoteException e) { 228 } 229 } 230 231 mRcsService = IRcsService.Stub.asInterface(b); 232 } 233 234 /** 235 * Death recipient class for monitoring RCS service. 236 */ 237 private class RcsServiceDeathRecipient implements IBinder.DeathRecipient { 238 @Override binderDied()239 public void binderDied() { 240 mRcsService = null; 241 mRcsPresence = null; 242 243 if (mContext != null) { 244 Intent intent = new Intent(ACTION_RCS_SERVICE_DIED); 245 intent.putExtra(EXTRA_SUBID, mSubId); 246 mContext.sendBroadcast(new Intent(intent)); 247 } 248 } 249 } 250 } 251