Merge "Display "No service" on status bar when SIM unready"
diff --git a/src/java/com/android/internal/telephony/cat/AppInterface.java b/src/java/com/android/internal/telephony/cat/AppInterface.java
old mode 100644
new mode 100755
index c78b7f8..1f2d3a0
--- a/src/java/com/android/internal/telephony/cat/AppInterface.java
+++ b/src/java/com/android/internal/telephony/cat/AppInterface.java
@@ -84,6 +84,7 @@
SET_UP_MENU(0x25),
SET_UP_CALL(0x10),
PROVIDE_LOCAL_INFORMATION(0x26),
+ LANGUAGE_NOTIFICATION(0x35),
OPEN_CHANNEL(0x40),
CLOSE_CHANNEL(0x41),
RECEIVE_DATA(0x42),
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
old mode 100644
new mode 100755
index 7e70212..cd7a756
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -16,15 +16,21 @@
package com.android.internal.telephony.cat;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.backup.BackupManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources.NotFoundException;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.LocaleList;
import android.os.Message;
+import android.os.RemoteException;
import android.os.SystemProperties;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -450,6 +456,18 @@
((CallSetupParams) cmdParams).mConfirmMsg.text = message.toString();
}
break;
+ case LANGUAGE_NOTIFICATION:
+ String language = ((LanguageParams) cmdParams).mLanguage;
+ ResultCode result = ResultCode.OK;
+ if (language != null && language.length() > 0) {
+ try {
+ changeLanguage(language);
+ } catch (RemoteException e) {
+ result = ResultCode.TERMINAL_CRNTLY_UNABLE_TO_PROCESS;
+ }
+ }
+ sendTerminalResponse(cmdParams.mCmdDet, result, false, 0, null);
+ return;
case OPEN_CHANNEL:
case CLOSE_CHANNEL:
case RECEIVE_DATA:
@@ -1129,4 +1147,13 @@
mCmdIf.reportStkServiceIsRunning(null);
}
}
+
+ private void changeLanguage(String language) throws RemoteException {
+ IActivityManager am = ActivityManagerNative.getDefault();
+ Configuration config = am.getConfiguration();
+ config.setLocales(new LocaleList(new Locale(language), LocaleList.getDefault()));
+ config.userSetLocale = true;
+ am.updatePersistentConfiguration(config);
+ BackupManager.dataChanged("com.android.providers.settings");
+ }
}
diff --git a/src/java/com/android/internal/telephony/cat/CommandParams.java b/src/java/com/android/internal/telephony/cat/CommandParams.java
old mode 100644
new mode 100755
index 7dfedab..59cd414
--- a/src/java/com/android/internal/telephony/cat/CommandParams.java
+++ b/src/java/com/android/internal/telephony/cat/CommandParams.java
@@ -150,6 +150,15 @@
}
}
+class LanguageParams extends CommandParams {
+ String mLanguage;
+
+ LanguageParams(CommandDetails cmdDet, String lang) {
+ super(cmdDet);
+ mLanguage = lang;
+ }
+}
+
class SelectItemParams extends CommandParams {
Menu mMenu = null;
boolean mLoadTitleIcon = false;
diff --git a/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java
index 3dd5337..eb92888 100644
--- a/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java
+++ b/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java
@@ -19,12 +19,15 @@
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
+import android.text.TextUtils;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.uicc.IccFileHandler;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
+
import static com.android.internal.telephony.cat.CatCmdMessage.
SetupEventListConstants.USER_ACTIVITY_EVENT;
import static com.android.internal.telephony.cat.CatCmdMessage.
@@ -47,6 +50,8 @@
private int mIconLoadState = LOAD_NO_ICON;
private RilMessageDecoder mCaller = null;
private boolean mloadIcon = false;
+ private String mSavedLanguage;
+ private String mRequestedLanguage;
// constants
static final int MSG_ID_LOAD_ICON_DONE = 1;
@@ -66,6 +71,10 @@
static final int DTTZ_SETTING = 0x03;
static final int LANGUAGE_SETTING = 0x04;
+ // Command Qualifier value for language notification command
+ static final int NON_SPECIFIC_LANGUAGE = 0x00;
+ static final int SPECIFIC_LANGUAGE = 0x01;
+
// As per TS 102.223 Annex C, Structure of CAT communications,
// the APDU length can be max 255 bytes. This leaves only 239 bytes for user
// input string. CMD details TLV + Device IDs TLV + Result TLV + Other
@@ -203,6 +212,9 @@
case PROVIDE_LOCAL_INFORMATION:
cmdPending = processProvideLocalInfo(cmdDet, ctlvs);
break;
+ case LANGUAGE_NOTIFICATION:
+ cmdPending = processLanguageNotification(cmdDet, ctlvs);
+ break;
case OPEN_CHANNEL:
case CLOSE_CHANNEL:
case RECEIVE_DATA:
@@ -1014,6 +1026,67 @@
return false;
}
+ /**
+ * Processes LANGUAGE_NOTIFICATION proactive command from the SIM card.
+ *
+ * The SPECIFIC_LANGUAGE notification sets the specified language.
+ * The NON_SPECIFIC_LANGUAGE notification restores the last specifically set language.
+ *
+ * @param cmdDet Command Details object retrieved from the proactive command object
+ * @param ctlvs List of ComprehensionTlv objects following Command Details
+ * object and Device Identities object within the proactive command
+ * @return false. This function always returns false meaning that the command
+ * processing is not pending and additional asynchronous processing
+ * is not required.
+ */
+ private boolean processLanguageNotification(CommandDetails cmdDet, List<ComprehensionTlv> ctlvs)
+ throws ResultException {
+ CatLog.d(this, "process Language Notification");
+
+ String desiredLanguage = null;
+ String currentLanguage = Locale.getDefault().getLanguage();
+ switch (cmdDet.commandQualifier) {
+ case NON_SPECIFIC_LANGUAGE:
+ if (!TextUtils.isEmpty(mSavedLanguage) && (!TextUtils.isEmpty(mRequestedLanguage)
+ && mRequestedLanguage.equals(currentLanguage))) {
+ CatLog.d(this, "Non-specific language notification changes the language "
+ + "setting back to " + mSavedLanguage);
+ desiredLanguage = mSavedLanguage;
+ }
+
+ mSavedLanguage = null;
+ mRequestedLanguage = null;
+ break;
+ case SPECIFIC_LANGUAGE:
+ ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.LANGUAGE, ctlvs);
+ if (ctlv != null) {
+ int valueLen = ctlv.getLength();
+ if (valueLen != 2) {
+ throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
+ }
+
+ byte[] rawValue = ctlv.getRawValue();
+ int valueIndex = ctlv.getValueIndex();
+ desiredLanguage = GsmAlphabet.gsm8BitUnpackedToString(rawValue, valueIndex, 2);
+
+ if (TextUtils.isEmpty(mSavedLanguage) || (!TextUtils.isEmpty(mRequestedLanguage)
+ && !mRequestedLanguage.equals(currentLanguage))) {
+ mSavedLanguage = currentLanguage;
+ }
+ mRequestedLanguage = desiredLanguage;
+ CatLog.d(this, "Specific language notification changes the language setting to "
+ + mRequestedLanguage);
+ }
+ break;
+ default:
+ CatLog.d(this, "LN[" + cmdDet.commandQualifier + "] Command Not Supported");
+ break;
+ }
+
+ mCmdParams = new LanguageParams(cmdDet, desiredLanguage);
+ return false;
+ }
+
private boolean processBIPClient(CommandDetails cmdDet,
List<ComprehensionTlv> ctlvs) throws ResultException {
AppInterface.CommandType commandType =
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 9b86712..03843a7 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -101,9 +101,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Deque;
import java.util.List;
/**
@@ -1030,6 +1028,9 @@
break;
case ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE:
error = CommandException.Error.RADIO_NOT_AVAILABLE;
+ break;
+ case ImsReasonInfo.CODE_FDN_BLOCKED:
+ error = CommandException.Error.FDN_CHECK_FAILURE;
default:
break;
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index b1013b1..b861b8f 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -16,6 +16,17 @@
package com.android.internal.telephony.imsphone;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_DATA;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_DATA_ASYNC;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_DATA_SYNC;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_FAX;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_MAX;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_NONE;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_PACKET;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_PAD;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_SMS;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
+
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
@@ -24,36 +35,24 @@
import android.os.Message;
import android.os.ResultReceiver;
import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
-import android.telephony.Rlog;
import com.android.ims.ImsException;
import com.android.ims.ImsReasonInfo;
import com.android.ims.ImsSsInfo;
import com.android.ims.ImsUtInterface;
import com.android.internal.telephony.CallForwardInfo;
-import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.uicc.IccRecords;
-
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_NONE;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_DATA;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_FAX;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_SMS;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_DATA_SYNC;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_DATA_ASYNC;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_PACKET;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_PAD;
-import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_MAX;
-
import com.android.internal.telephony.MmiCode;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.uicc.IccRecords;
-import java.util.regex.Pattern;
import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* The motto for this file is:
@@ -1148,6 +1147,14 @@
}
private CharSequence getErrorMessage(AsyncResult ar) {
+ if (ar.exception instanceof CommandException) {
+ CommandException.Error err = ((CommandException) (ar.exception)).getCommandError();
+ if (err == CommandException.Error.FDN_CHECK_FAILURE) {
+ Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
+ return mContext.getText(com.android.internal.R.string.mmiFdnError);
+ }
+ }
+
return mContext.getText(com.android.internal.R.string.mmiError);
}
@@ -1192,18 +1199,15 @@
if (err.getCommandError() == CommandException.Error.PASSWORD_INCORRECT) {
sb.append(mContext.getText(
com.android.internal.R.string.passwordIncorrect));
+ } else if (err.getCommandError() == CommandException.Error.FDN_CHECK_FAILURE) {
+ sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
} else if (err.getMessage() != null) {
sb.append(err.getMessage());
} else {
sb.append(mContext.getText(com.android.internal.R.string.mmiError));
}
- } else {
- ImsException error = (ImsException) ar.exception;
- if (error.getMessage() != null) {
- sb.append(error.getMessage());
- } else {
- sb.append(getErrorMessage(ar));
- }
+ } else if (ar.exception instanceof ImsException) {
+ sb.append(getImsErrorMessage(ar));
}
} else if (isActivate()) {
mState = State.COMPLETE;
@@ -1336,12 +1340,7 @@
mState = State.FAILED;
if (ar.exception instanceof ImsException) {
- ImsException error = (ImsException) ar.exception;
- if (error.getMessage() != null) {
- sb.append(error.getMessage());
- } else {
- sb.append(getErrorMessage(ar));
- }
+ sb.append(getImsErrorMessage(ar));
}
else {
sb.append(getErrorMessage(ar));
@@ -1397,21 +1396,14 @@
StringBuilder sb = new StringBuilder(getScString());
sb.append("\n");
+ mState = State.FAILED;
if (ar.exception != null) {
- mState = State.FAILED;
-
if (ar.exception instanceof ImsException) {
- ImsException error = (ImsException) ar.exception;
- if (error.getMessage() != null) {
- sb.append(error.getMessage());
- } else {
- sb.append(getErrorMessage(ar));
- }
+ sb.append(getImsErrorMessage(ar));
} else {
sb.append(getErrorMessage(ar));
}
} else {
- mState = State.FAILED;
ImsSsInfo ssInfo = null;
if (ar.result instanceof Bundle) {
Rlog.d(LOG_TAG, "onSuppSvcQueryComplete: Received CLIP/COLP/COLR Response.");
@@ -1462,12 +1454,7 @@
mState = State.FAILED;
if (ar.exception instanceof ImsException) {
- ImsException error = (ImsException) ar.exception;
- if (error.getMessage() != null) {
- sb.append(error.getMessage());
- } else {
- sb.append(getErrorMessage(ar));
- }
+ sb.append(getImsErrorMessage(ar));
} else {
sb.append(getErrorMessage(ar));
}
@@ -1501,14 +1488,8 @@
mState = State.FAILED;
if (ar.exception != null) {
-
if (ar.exception instanceof ImsException) {
- ImsException error = (ImsException) ar.exception;
- if (error.getMessage() != null) {
- sb.append(error.getMessage());
- } else {
- sb.append(getErrorMessage(ar));
- }
+ sb.append(getImsErrorMessage(ar));
}
} else {
Bundle ssInfo = (Bundle) ar.result;
@@ -1599,12 +1580,7 @@
mState = State.FAILED;
if (ar.exception instanceof ImsException) {
- ImsException error = (ImsException) ar.exception;
- if (error.getMessage() != null) {
- sb.append(error.getMessage());
- } else {
- sb.append(getErrorMessage(ar));
- }
+ sb.append(getImsErrorMessage(ar));
} else {
sb.append(getErrorMessage(ar));
}
@@ -1652,6 +1628,17 @@
return sb;
}
+ private CharSequence getImsErrorMessage(AsyncResult ar) {
+ ImsException error = (ImsException) ar.exception;
+ if (error.getCode() == ImsReasonInfo.CODE_FDN_BLOCKED) {
+ return mContext.getText(com.android.internal.R.string.mmiFdnError);
+ } else if (error.getMessage() != null) {
+ return error.getMessage();
+ } else {
+ return getErrorMessage(ar);
+ }
+ }
+
@Override
public ResultReceiver getUssdCallbackReceiver() {
return this.mCallbackReceiver;