blob: 4cc7011b214ccd14d44ca42c57c96a66529ea0b0 [file] [log] [blame]
/*
* Copyright (c) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ims;
import java.util.HashMap;
import java.util.Map;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.Rlog;
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
/**
* Provides APIs for the supplementary service settings using IMS (Ut interface).
* It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol)
* over the Ut interface for manipulating supplementary services).
*
* @hide
*/
public class ImsUt implements ImsUtInterface {
/**
* Key string for an additional supplementary service configurations.
*/
/**
* Actions : string format of ImsUtInterface#ACTION_xxx
* "0" (deactivation), "1" (activation), "2" (not_used),
* "3" (registration), "4" (erasure), "5" (Interrogation)
*/
public static final String KEY_ACTION = "action";
/**
* Categories :
* "OIP", "OIR", "TIP", "TIR", "CDIV", "CB", "CW", "CONF",
* "ACR", "MCID", "ECT", "CCBS", "AOC", "MWI", "FA", "CAT"
*
* Detailed parameter name will be determined according to the properties
* of the supplementary service configuration.
*/
public static final String KEY_CATEGORY = "category";
public static final String CATEGORY_OIP = "OIP";
public static final String CATEGORY_OIR = "OIR";
public static final String CATEGORY_TIP = "TIP";
public static final String CATEGORY_TIR = "TIR";
public static final String CATEGORY_CDIV = "CDIV";
public static final String CATEGORY_CB = "CB";
public static final String CATEGORY_CW = "CW";
public static final String CATEGORY_CONF = "CONF";
private static final String TAG = "ImsUt";
private static final boolean DBG = true;
// For synchronization of private variables
private Object mLockObj = new Object();
private final IImsUt miUt;
private HashMap<Integer, Message> mPendingCmds =
new HashMap<Integer, Message>();
public ImsUt(IImsUt iUt) {
miUt = iUt;
if (miUt != null) {
try {
miUt.setListener(new IImsUtListenerProxy());
} catch (RemoteException e) {
}
}
}
public void close() {
synchronized(mLockObj) {
if (miUt != null) {
try {
miUt.close();
} catch (RemoteException e) {
}
}
if (!mPendingCmds.isEmpty()) {
Map.Entry<Integer, Message>[] entries =
mPendingCmds.entrySet().toArray(new Map.Entry[mPendingCmds.size()]);
for (Map.Entry<Integer, Message> entry : entries) {
sendFailureReport(entry.getValue(),
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
mPendingCmds.clear();
}
}
}
/**
* Operations for the supplementary service configuration
*/
/**
* Retrieves the configuration of the call barring.
*
* @param cbType type of call barring to be queried; ImsUtInterface#CB_XXX
* @param result message to pass the result of this operation
* The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}.
*/
@Override
public void queryCallBarring(int cbType, Message result) {
if (DBG) {
log("queryCallBarring :: Ut=" + miUt + ", cbType=" + cbType);
}
synchronized(mLockObj) {
try {
int id = miUt.queryCallBarring(cbType);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Retrieves the configuration of the call forward.
* The return value of ((AsyncResult)result.obj) is an array of {@link ImsCallForwardInfo}.
*/
@Override
public void queryCallForward(int condition, String number, Message result) {
if (DBG) {
log("queryCallForward :: Ut=" + miUt + ", condition=" + condition
+ ", number=" + Rlog.pii(TAG, number));
}
synchronized(mLockObj) {
try {
int id = miUt.queryCallForward(condition, number);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Retrieves the configuration of the call waiting.
* The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}.
*/
@Override
public void queryCallWaiting(Message result) {
if (DBG) {
log("queryCallWaiting :: Ut=" + miUt);
}
synchronized(mLockObj) {
try {
int id = miUt.queryCallWaiting();
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Retrieves the default CLIR setting.
*/
@Override
public void queryCLIR(Message result) {
if (DBG) {
log("queryCLIR :: Ut=" + miUt);
}
synchronized(mLockObj) {
try {
int id = miUt.queryCLIR();
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Retrieves the CLIP call setting.
*/
public void queryCLIP(Message result) {
if (DBG) {
log("queryCLIP :: Ut=" + miUt);
}
synchronized(mLockObj) {
try {
int id = miUt.queryCLIP();
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Retrieves the COLR call setting.
*/
public void queryCOLR(Message result) {
if (DBG) {
log("queryCOLR :: Ut=" + miUt);
}
synchronized(mLockObj) {
try {
int id = miUt.queryCOLR();
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Retrieves the COLP call setting.
*/
public void queryCOLP(Message result) {
if (DBG) {
log("queryCOLP :: Ut=" + miUt);
}
synchronized(mLockObj) {
try {
int id = miUt.queryCOLP();
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Modifies the configuration of the call barring.
*/
@Override
public void updateCallBarring(int cbType, int action, Message result, String[] barrList) {
if (DBG) {
if (barrList != null) {
String bList = new String();
for (int i = 0; i < barrList.length; i++) {
bList.concat(barrList[i] + " ");
}
log("updateCallBarring :: Ut=" + miUt + ", cbType=" + cbType
+ ", action=" + action + ", barrList=" + bList);
}
else {
log("updateCallBarring :: Ut=" + miUt + ", cbType=" + cbType
+ ", action=" + action);
}
}
synchronized(mLockObj) {
try {
int id = miUt.updateCallBarring(cbType, action, barrList);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Modifies the configuration of the call forward.
*/
@Override
public void updateCallForward(int action, int condition, String number,
int serviceClass, int timeSeconds, Message result) {
if (DBG) {
log("updateCallForward :: Ut=" + miUt + ", action=" + action
+ ", condition=" + condition + ", number=" + Rlog.pii(TAG, number)
+ ", serviceClass=" + serviceClass + ", timeSeconds=" + timeSeconds);
}
synchronized(mLockObj) {
try {
int id = miUt.updateCallForward(action, condition, number, serviceClass, timeSeconds);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Modifies the configuration of the call waiting.
*/
@Override
public void updateCallWaiting(boolean enable, int serviceClass, Message result) {
if (DBG) {
log("updateCallWaiting :: Ut=" + miUt + ", enable=" + enable
+ ",serviceClass=" + serviceClass);
}
synchronized(mLockObj) {
try {
int id = miUt.updateCallWaiting(enable, serviceClass);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Updates the configuration of the CLIR supplementary service.
*/
@Override
public void updateCLIR(int clirMode, Message result) {
if (DBG) {
log("updateCLIR :: Ut=" + miUt + ", clirMode=" + clirMode);
}
synchronized(mLockObj) {
try {
int id = miUt.updateCLIR(clirMode);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Updates the configuration of the CLIP supplementary service.
*/
@Override
public void updateCLIP(boolean enable, Message result) {
if (DBG) {
log("updateCLIP :: Ut=" + miUt + ", enable=" + enable);
}
synchronized(mLockObj) {
try {
int id = miUt.updateCLIP(enable);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Updates the configuration of the COLR supplementary service.
*/
@Override
public void updateCOLR(int presentation, Message result) {
if (DBG) {
log("updateCOLR :: Ut=" + miUt + ", presentation=" + presentation);
}
synchronized(mLockObj) {
try {
int id = miUt.updateCOLR(presentation);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
/**
* Updates the configuration of the COLP supplementary service.
*/
@Override
public void updateCOLP(boolean enable, Message result) {
if (DBG) {
log("updateCallWaiting :: Ut=" + miUt + ", enable=" + enable);
}
synchronized(mLockObj) {
try {
int id = miUt.updateCOLP(enable);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
public void transact(Bundle ssInfo, Message result) {
if (DBG) {
log("transact :: Ut=" + miUt + ", ssInfo=" + ssInfo);
}
synchronized(mLockObj) {
try {
int id = miUt.transact(ssInfo);
if (id < 0) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
return;
}
mPendingCmds.put(Integer.valueOf(id), result);
} catch (RemoteException e) {
sendFailureReport(result,
new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0));
}
}
}
private void sendFailureReport(Message result, ImsReasonInfo error) {
if (result == null || error == null) {
return;
}
String errorString;
// If ImsReasonInfo object does not have a String error code, use a
// default error string.
if (error.mExtraMessage == null) {
errorString = Resources.getSystem().getString(
com.android.internal.R.string.mmiError);
}
else {
errorString = new String(error.mExtraMessage);
}
AsyncResult.forMessage(result, null, new ImsException(errorString, error.mCode));
result.sendToTarget();
}
private void sendSuccessReport(Message result) {
if (result == null) {
return;
}
AsyncResult.forMessage(result, null, null);
result.sendToTarget();
}
private void sendSuccessReport(Message result, Object ssInfo) {
if (result == null) {
return;
}
AsyncResult.forMessage(result, ssInfo, null);
result.sendToTarget();
}
private void log(String s) {
Rlog.d(TAG, s);
}
private void loge(String s) {
Rlog.e(TAG, s);
}
private void loge(String s, Throwable t) {
Rlog.e(TAG, s, t);
}
/**
* A listener type for the result of the supplementary service configuration.
*/
private class IImsUtListenerProxy extends IImsUtListener.Stub {
/**
* Notifies the result of the supplementary service configuration udpate.
*/
@Override
public void utConfigurationUpdated(IImsUt ut, int id) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendSuccessReport(mPendingCmds.get(key));
mPendingCmds.remove(key);
}
}
@Override
public void utConfigurationUpdateFailed(IImsUt ut, int id, ImsReasonInfo error) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendFailureReport(mPendingCmds.get(key), error);
mPendingCmds.remove(key);
}
}
/**
* Notifies the result of the supplementary service configuration query.
*/
@Override
public void utConfigurationQueried(IImsUt ut, int id, Bundle ssInfo) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendSuccessReport(mPendingCmds.get(key), ssInfo);
mPendingCmds.remove(key);
}
}
@Override
public void utConfigurationQueryFailed(IImsUt ut, int id, ImsReasonInfo error) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendFailureReport(mPendingCmds.get(key), error);
mPendingCmds.remove(key);
}
}
/**
* Notifies the status of the call barring supplementary service.
*/
@Override
public void utConfigurationCallBarringQueried(IImsUt ut,
int id, ImsSsInfo[] cbInfo) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendSuccessReport(mPendingCmds.get(key), cbInfo);
mPendingCmds.remove(key);
}
}
/**
* Notifies the status of the call forwarding supplementary service.
*/
@Override
public void utConfigurationCallForwardQueried(IImsUt ut,
int id, ImsCallForwardInfo[] cfInfo) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendSuccessReport(mPendingCmds.get(key), cfInfo);
mPendingCmds.remove(key);
}
}
/**
* Notifies the status of the call waiting supplementary service.
*/
@Override
public void utConfigurationCallWaitingQueried(IImsUt ut,
int id, ImsSsInfo[] cwInfo) {
Integer key = Integer.valueOf(id);
synchronized(mLockObj) {
sendSuccessReport(mPendingCmds.get(key), cwInfo);
mPendingCmds.remove(key);
}
}
}
}