Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Закрытый API - доступ открыт

#java #android #модемы


Уже почти целую неделю ищу способы пробиться в com.android.internal.telephony.IccCard
и овладеть методом supplyDepersonalization(). Тем, кто тоже будет копать в эту сторону
- ничего не получится. Даже с помощью рефлексии - это невозможно.
Единственный способ (не знаю, первый ли я):


Найти на устройстве (с правами root) фреймворк модема system/framework/telephony-common.jar
Любым архиватором достать из него скомпилированный classes.dex
"Превратить" его в jar утилитой dex2jar
И добавить полученный архив в вашу среду разработки


Лично у меня AIDE и я просто разархивировал android.jar и добавил в его содержимое
полученный ранее архив.

В итоге

Теперь мы можем написать в секции импортов, например, так

import com.android.internal.telephony.RIL;


И делать все, что хочется. Дело в том, что весь код, связанный с добавленными классами
успешно скомпилируется и будет выполняться. Я это проверил, вызывая методы в разных
классах и получая возвращаемые значения. 

Теперь к делу

Собственно, сам вопрос, я пытаюсь получить интерфейс IccCard и делаю так

PhoneFactory.makeDefaultPhone(this);
Phone p = PhoneFactory.getDefaultPhone();
IccCard i = p.getIccCard();
boolean x = i.getIccLockEnabled();


В итоге приложение зависает (и даже не показывает простую разметку) при выполнении
метода makeDefaultPhone(). Мне стало интересно почему и я полез его искать:

public static void makeDefaultPhone(Context context
    synchronized(Phone.class) {
if (!sMadeDefaults) {
sLooper = Looper.myLooper();
sContext = context;
if (sLooper == null) {
throw new RuntimeException("PhoneFactory.makeDefaultPhone must be called from Looper
thread");
}
int retryCount = 0;
for(;;) {
boolean hasException = false;
retryCount ++;
try {
// use UNIX domain socket to
// prevent subsequent initialization
new LocalServerSocket("com.android.internal.telephony");
} catch (java.io.IOException ex) {
hasException = true;
}
if ( !hasException ) {
break;
} else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
throw new RuntimeException("PhoneFactory probably already running");
} else {
try {
Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
} catch (InterruptedException er) {
}
}
}
sPhoneNotifier = new DefaultPhoneNotifier();
// Get preferred network mode
int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
preferredNetworkMode = Phone.NT_MODE_GLOBAL;
}
int networkMode = Settings.Global.getInt(context.getContentResolver(), Settings.Global.PREFERRED_NETWORK_MODE,
preferredNetworkMode);
Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
//reads the system properties and makes commandsinterface
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
// Instantiate UiccController so that all other classes can just call getInstance()
UiccController.make(context, sCommandsInterface);
int phoneType = TelephonyManager.getPhoneType(networkMode);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
Rlog.i(LOG_TAG, "Creating GSMPhone");
sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier));
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
switch (TelephonyManager.getLteOnCdmaModeStatic()) {
case PhoneConstants.LTE_ON_CDMA_TRUE:
Rlog.i(LOG_TAG, "Creating CDMALTEPhone");
sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, sCommandsInterface, sPhoneNotifier));
break;
case PhoneConstants.LTE_ON_CDMA_FALSE:
default:
Rlog.i(LOG_TAG, "Creating CDMAPhone");
sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier));
break;
}
}
// Ensure that we have a default SMS app. Requesting the app with
// updateIfNeeded set to true is enough to configure a default SMS app.
ComponentName componentName = SmsApplication.getDefaultSmsApplication(context, true
/* updateIfNeeded */);
String packageName = "NONE";
if (componentName != null) {
packageName = componentName.getPackageName();
}
Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);
// Set up monitor to watch for changes to SMS packages
SmsApplication.initSmsPackageMonitor(context);
sMadeDefaults = true;
}
}
}


Ну, что ж, внимательно почитав код и разобрав каждую строчку, я понял, что мне не
нужно обращаться к PhoneFactory. Достаточно создать Phone самому. Пытаюсь так:

int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(this);
            PhoneNotifier sPhoneNotifier = new DefaultPhoneNotifier();
            RIL sRIL = new RIL(this, 9, cdmaSubscription);
            CommandsInterface sCommandsInterface = sRIL;
            GSMPhone gsmPhone = new GSMPhone(this, sCommandsInterface, sPhoneNotifier);
Phone sProxyPhone = new PhoneProxy(gsmPhone);


DefaultPhoneNotifier имеет конструктор с модификатором доступа protected. Причем,
в официальной документацит его вообще нет (public). Мой фреймворк был модифицирован
производителем. Что можно в таком случае предпринять? Можно ли создать PhoneNotifier
как-нибудь по другому? Как отправлять код разлочки по-другому? 

UPDATE

Фреймворк на тестируемом устройстве вовсе не модифицирован. Заметил, что в разных
версиях андроида где-то protected есть, а где то нет. 
    


Ответы

Ответ 1



жениться бы вам надо, барин... Все что делает supplyDepersonalization() - это шлет модему команду AT+CLCK="PS",0,. Проблема в том, что PS (т.е. SIM Lock) услуга давно не поддерживается производителями модемов (baseband). Попробуйте послать модему команду AT+CLCK=? которая возвращает список поддерживаемых вариантов залочки. И если в нем не будет PS - то никакое извращение на стороне Андроида (application processor) вам не поможет.

Комментариев нет:

Отправить комментарий