Уже почти целую неделю ищу способы пробиться в 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,
Попробуйте послать модему команду AT+CLCK=? которая возвращает список поддерживаемых вариантов залочки. И если в нем не будет PS - то никакое извращение на стороне Андроида (application processor) вам не поможет.
Комментариев нет:
Отправить комментарий