Страницы

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

вторник, 9 октября 2018 г.

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

Уже почти целую неделю ищу способы пробиться в 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 есть, а где то нет.


Ответ

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

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

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