Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8770b406 authored by Takanori Nakano's avatar Takanori Nakano Committed by Yoshiaki Naka
Browse files

Handle LANGUAGE NOTIFICATION command

The terminal shall handle LANGUAGE NOTIFICATION command and return
TERMINAL RESPONSE (OK) to the UICC in order to pass the test cases
described in the section 27.22.4.25 of ETSI TS 102 384.

Bug: 30175964
Test: manual - Confirmed that the command works as expected.

Change-Id: Ia1d09cb19021742e4fcc2f8e0d15140853d553cb
parent 51a49303
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ public interface AppInterface {
        SET_UP_MENU(0x25),
        SET_UP_CALL(0x10),
        PROVIDE_LOCAL_INFORMATION(0x26),
        LANGUAGE_NOTIFICATION(0x35),
        OPEN_CHANNEL(0x40),
        CLOSE_CHANNEL(0x41),
        RECEIVE_DATA(0x42),
+27 −0
Original line number Diff line number Diff line
@@ -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 @@ public class CatService extends Handler implements AppInterface {
                    ((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:
@@ -1117,4 +1135,13 @@ public class CatService extends Handler implements AppInterface {
            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");
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -150,6 +150,15 @@ class CallSetupParams extends CommandParams {
    }
}

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;
+73 −0
Original line number Diff line number Diff line
@@ -19,12 +19,15 @@ package com.android.internal.telephony.cat;
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 @@ class CommandParamsFactory extends Handler {
    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 @@ class CommandParamsFactory extends Handler {
    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 @@ class CommandParamsFactory extends Handler {
             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:
@@ -1012,6 +1024,67 @@ class CommandParamsFactory extends Handler {
        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 =