blob: c226b62eef4391a1559fdc4f86d12d747d557f89 [file] [log] [blame]
/*
* Copyright (C) 2006 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.internal.telephony.cdma;
import android.content.Context;
import android.os.*;
import android.util.Log;
import com.android.internal.telephony.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* {@hide}
*
*/
public final class FeatureCode extends Handler implements MmiCode {
static final String LOG_TAG = "CDMA";
//***** Constants
// Call Forwarding
static final String FC_CF_ACTIVATE = "72";
static final String FC_CF_DEACTIVATE = "73";
static final String FC_CF_FORWARD_TO_NUMBER = "56";
// Call Forwarding Busy Line
static final String FC_CFBL_ACTIVATE = "90";
static final String FC_CFBL_DEACTIVATE = "91";
static final String FC_CFBL_FORWARD_TO_NUMBER = "40";
// Call Forwarding Don't Answer
static final String FC_CFDA_ACTIVATE = "92";
static final String FC_CFDA_DEACTIVATE = "93";
static final String FC_CFDA_FORWARD_TO_NUMBER = "42";
// Cancel Call Waiting
static final String FC_CCW = "70";
// Usage Sensitive Three-way Calling
static final String FC_3WC = "71";
// Do Not Disturb
static final String FC_DND_ACTIVATE = "78";
static final String FC_DND_DEACTIVATE = "79";
// Who Called Me?
static final String FC_WHO = "51";
// Rejection of Undesired Annoying Calls
static final String FC_RUAC_ACTIVATE = "60";
static final String FC_RUAC_DEACTIVATE = "80";
// Calling Number Delivery
// Calling Number Identification Presentation
static final String FC_CNIP = "65";
// Calling Number Identification Restriction
static final String FC_CNIR = "85";
//***** Event Constants
static final int EVENT_SET_COMPLETE = 1;
static final int EVENT_CDMA_FLASH_COMPLETED = 2;
//***** Instance Variables
CDMAPhone phone;
Context context;
String action; // '*' in CDMA
String sc; // Service Code
String poundString; // Entire Flash string
String dialingNumber;
/** Set to true in processCode, not at newFromDialString time */
State state = State.PENDING;
CharSequence message;
//***** Class Variables
// Flash Code Pattern
static Pattern sPatternSuppService = Pattern.compile(
"((\\*)(\\d{2,3})(#?)([^*#]*)?)(.*)");
/* 1 2 3 4 5 6
1 = Full string up to and including #
2 = action
3 = service code
4 = separator
5 = dialing number
*/
static final int MATCH_GROUP_POUND_STRING = 1;
static final int MATCH_GROUP_ACTION_STRING = 2;
static final int MATCH_GROUP_SERVICE_CODE = 3;
static final int MATCH_GROUP_DIALING_NUMBER = 5;
//***** Public Class methods
/**
* Some dial strings in CDMA are defined to do non-call setup
* things, such as set supplementary service settings (eg, call
* forwarding). These are generally referred to as "Feature Codes".
* We look to see if the dial string contains a valid Feature code (potentially
* with a dial string at the end as well) and return info here.
*
* If the dial string contains no Feature code, we return an instance with
* only "dialingNumber" set
*
* Please see also S.R0006-000-A v2.0 "Wireless Features Description"
*/
static FeatureCode newFromDialString(String dialString, CDMAPhone phone) {
Matcher m;
FeatureCode ret = null;
m = sPatternSuppService.matcher(dialString);
// Is this formatted like a standard supplementary service code?
if (m.matches()) {
ret = new FeatureCode(phone);
ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION_STRING));
ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
ret.dialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
}
return ret;
}
//***** Private Class methods
/** make empty strings be null.
* Java regexp returns empty strings for empty groups
*/
private static String makeEmptyNull (String s) {
if (s != null && s.length() == 0) return null;
return s;
}
/** returns true of the string is empty or null */
private static boolean isEmptyOrNull(CharSequence s) {
return s == null || (s.length() == 0);
}
static boolean isServiceCodeCallForwarding(String sc) {
return sc != null &&
(sc.equals(FC_CF_ACTIVATE)
|| sc.equals(FC_CF_DEACTIVATE) || sc.equals(FC_CF_FORWARD_TO_NUMBER)
|| sc.equals(FC_CFBL_ACTIVATE) || sc.equals(FC_CFBL_DEACTIVATE)
|| sc.equals(FC_CFBL_FORWARD_TO_NUMBER) || sc.equals(FC_CFDA_ACTIVATE)
|| sc.equals(FC_CFDA_DEACTIVATE) || sc.equals(FC_CFDA_FORWARD_TO_NUMBER));
}
static boolean isServiceCodeCallWaiting(String sc) {
return sc != null && sc.equals(FC_CCW);
}
static boolean isServiceCodeThreeWayCalling(String sc) {
return sc != null && sc.equals(FC_3WC);
}
static boolean isServiceCodeAnnoyingCalls(String sc) {
return sc != null &&
(sc.equals(FC_RUAC_ACTIVATE)
|| sc.equals(FC_RUAC_DEACTIVATE));
}
static boolean isServiceCodeCallingNumberDelivery(String sc) {
return sc != null &&
(sc.equals(FC_CNIP)
|| sc.equals(FC_CNIR));
}
static boolean isServiceCodeDoNotDisturb(String sc) {
return sc != null &&
(sc.equals(FC_DND_ACTIVATE)
|| sc.equals(FC_DND_DEACTIVATE));
}
//***** Constructor
FeatureCode (CDMAPhone phone) {
super(phone.getHandler().getLooper());
this.phone = phone;
this.context = phone.getContext();
}
//***** MmiCode implementation
public State getState() {
return state;
}
public CharSequence getMessage() {
return message;
}
// inherited javadoc suffices
public void cancel() {
//Not used here
}
public boolean isCancelable() {
Log.e(LOG_TAG, "isCancelable: not used in CDMA");
return false;
}
public boolean isUssdRequest() {
Log.e(LOG_TAG, "isUssdRequest: not used in CDMA");
return false;
}
/** Process a Flash Code...anything that isn't a dialing number */
void processCode () {
Log.d(LOG_TAG, "send feature code...");
phone.mCM.sendCDMAFeatureCode(this.poundString,
obtainMessage(EVENT_CDMA_FLASH_COMPLETED));
}
/** Called from CDMAPhone.handleMessage; not a Handler subclass */
public void handleMessage (Message msg) {
AsyncResult ar;
switch (msg.what) {
case EVENT_SET_COMPLETE:
ar = (AsyncResult) (msg.obj);
onSetComplete(ar);
break;
case EVENT_CDMA_FLASH_COMPLETED:
ar = (AsyncResult) (msg.obj);
if (ar.exception != null) {
state = State.FAILED;
message = context.getText(com.android.internal.R.string.fcError);
} else {
state = State.COMPLETE;
message = context.getText(com.android.internal.R.string.fcComplete);
}
phone.onFeatureCodeDone(this);
break;
}
}
//***** Private instance methods
private CharSequence getScString() {
if (sc != null) {
if (isServiceCodeCallForwarding(sc)) {
return context.getText(com.android.internal.R.string.CfMmi);
} else if (isServiceCodeCallWaiting(sc)) {
return context.getText(com.android.internal.R.string.CwMmi);
} else if (sc.equals(FC_CNIP)) {
return context.getText(com.android.internal.R.string.CnipMmi);
} else if (sc.equals(FC_CNIR)) {
return context.getText(com.android.internal.R.string.CnirMmi);
} else if (isServiceCodeThreeWayCalling(sc)) {
return context.getText(com.android.internal.R.string.ThreeWCMmi);
} else if (isServiceCodeAnnoyingCalls(sc)) {
return context.getText(com.android.internal.R.string.RuacMmi);
} else if (isServiceCodeCallingNumberDelivery(sc)) {
return context.getText(com.android.internal.R.string.CndMmi);
} else if (isServiceCodeDoNotDisturb(sc)) {
return context.getText(com.android.internal.R.string.DndMmi);
}
}
return "";
}
private void onSetComplete(AsyncResult ar){
StringBuilder sb = new StringBuilder(getScString());
sb.append("\n");
if (ar.exception != null) {
state = State.FAILED;
sb.append(context.getText(com.android.internal.R.string.mmiError));
} else {
state = State.FAILED;
sb.append(context.getText(com.android.internal.R.string.mmiError));
}
message = sb;
phone.onFeatureCodeDone(this);
}
}