Permalink
Browse files

2G/3G toggle for applications

Allow applications (like Tasker) to change Network mode.

Patch-set 3: I don't know what is wrong with this commit, for me is working well.

Change-Id: Ic59668716f735bab491df9905bfe99bae90afa31
Signed-off-by: Petr Reznicek <kecinzer@gmail.com>
  • Loading branch information...
1 parent b18cbd7 commit d1ca2d45f27733788f451b52b771239b8f7b9a09 @kecinzer kecinzer committed Aug 6, 2012
Showing with 200 additions and 1 deletion.
  1. +12 −1 AndroidManifest.xml
  2. +4 −0 res/values-cs/strings.xml
  3. +3 −0 res/values/strings.xml
  4. +181 −0 src/com/android/phone/PhoneToggler.java
View
@@ -520,6 +520,17 @@
<action android:name="com.android.phone.ACTION_SEND_SMS_FROM_NOTIFICATION" />
</intent-filter>
</receiver>
-
+ <receiver android:name="com.android.phone.PhoneToggler" android:permission="com.android.phone.CHANGE_NETWORK_MODE">
+ <intent-filter>
+ <action android:name="com.android.internal.telephony.REQUEST_NETWORK_MODE" />
+ <action android:name="com.android.internal.telephony.MODIFY_NETWORK_MODE" />
+ </intent-filter>
+ </receiver>
</application>
+ <permission
+ android:description="@string/per_change_mobile_network_desc"
+ android:label="@string/per_change_mobile_network"
+ android:name="com.android.phone.CHANGE_NETWORK_MODE"
+ android:permissionGroup="android.permission-group.COST_MONEY"
+ android:protectionLevel="dangerous" />
</manifest>
@@ -621,6 +621,7 @@
<string name="vibrate_on_ring_title" msgid="9197564612065258960">"Vibrace při vyzvánění"</string>
<string name="dtmf_tone_enable_title" msgid="827601042915852989">"Tóny při dotyku číselníku"</string>
<string name="preference_category_ringtone" msgid="9007490591910078324">"Vyzvánění"</string>
+
<string name="ring_delay_title">Opožděné vyzvánění</string>
<string name="ring_delay_summary">Nastavit zpoždění vyzvánění</string>
<string-array name="ring_delay_entries">
@@ -629,4 +630,7 @@
<item>6 sekund</item>
<item>9 sekund</item>
</string-array>
+
+ <string name="per_change_mobile_network">Změnit síť (2G/3G)</string>
+ <string name="per_change_mobile_network_desc">Aplikace s tímto oprávněním může kdykoliv přepínat mezi 2G/3G sítí.</string>
</resources>
View
@@ -1436,6 +1436,9 @@
<!-- Description of the decline on target in the Slide unlock screen. [CHAR LIMIT=NONE] -->
<string name="description_target_decline">Decline</string>
+ <string name="per_change_mobile_network">Change network (2G/3G)</string>
+ <string name="per_change_mobile_network_desc">Application with this permission can, at any time, change between 2G Data and 3G data. 3G is faster, consumes more batery, and can also cost you more money.</string>
+
<!-- Dialog title for the vibration settings for voicemail notifications [CHAR LIMIT=40] -->
<string name="voicemail_notification_vibrate_when_title" msgid="8731372580674292759">Vibrate</string>
<!-- Dialog title for the vibration settings for voice mail notifications [CHAR LIMIT=40]-->
@@ -0,0 +1,181 @@
+package com.android.phone;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+public class PhoneToggler extends BroadcastReceiver {
+
+ /** Used for brodcasting network data change and receive new mode **/
+ public static final String NETWORK_MODE_CHANGED="com.android.internal.telephony.NETWORK_MODE_CHANGED";
+ public static final String REQUEST_NETWORK_MODE="com.android.internal.telephony.REQUEST_NETWORK_MODE";
+ public static final String MODIFY_NETWORK_MODE="com.android.internal.telephony.MODIFY_NETWORK_MODE";
+ public static final String MOBILE_DATA_CHANGED="com.android.internal.telephony.MOBILE_DATA_CHANGED";
+ public static final String NETWORK_MODE = "networkMode";
+
+ public static final String CHANGE_NETWORK_MODE_PERM= "com.android.phone.CHANGE_NETWORK_MODE";
+ private static final String LOG_TAG = "PhoneToggler";
+ private static final boolean DBG = true;
+
+ private Phone mPhone;
+ private MyHandler mHandler;
+
+
+ private Phone getPhone() {
+ if (mPhone==null) mPhone = PhoneFactory.getDefaultPhone();
+ return mPhone;
+ }
+
+ private MyHandler getHandler() {
+ if (mHandler==null) mHandler = new MyHandler();
+ return mHandler;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(MODIFY_NETWORK_MODE)) {
+ if (DBG) Log.d(LOG_TAG,"Got modify intent");
+ if (intent.getExtras()!=null) {
+ int networkMode = intent.getExtras().getInt(NETWORK_MODE);
+ boolean networkModeOk = false;
+ int phoneType = getPhone().getPhoneType();
+ boolean isLteOnCdma = getPhone().getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE;
+
+ if (phoneType == Phone.PHONE_TYPE_GSM) {
+ if (networkMode == Phone.NT_MODE_GSM_ONLY
+ || networkMode == Phone.NT_MODE_GSM_UMTS
+ || networkMode == Phone.NT_MODE_WCDMA_PREF
+ || networkMode == Phone.NT_MODE_WCDMA_ONLY) {
+ networkModeOk = true;
+ }
+ } else if (phoneType == Phone.PHONE_TYPE_CDMA) {
+ if (networkMode == Phone.NT_MODE_CDMA
+ || networkMode == Phone.NT_MODE_CDMA_NO_EVDO
+ || networkMode == Phone.NT_MODE_EVDO_NO_CDMA) {
+ networkModeOk = true;
+ }
+ }
+ if (context.getResources().getBoolean(R.bool.world_phone) || isLteOnCdma) {
+ if (networkMode == Phone.NT_MODE_GLOBAL) {
+ networkModeOk = true;
+ }
+ }
+
+ if (networkModeOk) {
+ if (DBG) Log.d(LOG_TAG,"Will modify it to: "+networkMode);
+ changeNetworkMode(networkMode);
+ if (DBG) Log.d(LOG_TAG,"Accepted modification of network mode to : "+networkMode);
+ } else {
+ Log.e(LOG_TAG,"Not accepted network mode: "+networkMode);
+ }
+ }
+ } else if (intent.getAction().equals(REQUEST_NETWORK_MODE)) {
+ if (DBG) Log.d(LOG_TAG,"Sending Intent with current phone network mode");
+ triggerIntent();
+ } else {
+ Log.e(LOG_TAG,"Not accepted intent: "+intent.getAction());
+ }
+ }
+
+ private void changeNetworkMode(int modemNetworkMode) {
+ getPhone().setPreferredNetworkType(modemNetworkMode, getHandler()
+ .obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE));
+
+ }
+
+ private void triggerIntent() {
+ getPhone().getPreferredNetworkType(getHandler()
+ .obtainMessage(MyHandler.MESSAGE_GET_PREFERRED_NETWORK_TYPE));
+ }
+
+ private class MyHandler extends Handler {
+
+ private static final int MESSAGE_GET_PREFERRED_NETWORK_TYPE = 0;
+ private static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 1;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_GET_PREFERRED_NETWORK_TYPE:
+ handleGetPreferredNetworkTypeResponse(msg);
+ break;
+
+ case MESSAGE_SET_PREFERRED_NETWORK_TYPE:
+ handleSetPreferredNetworkTypeResponse(msg);
+ break;
+ }
+ }
+
+ private void handleGetPreferredNetworkTypeResponse(Message msg) {
+ AsyncResult ar = (AsyncResult) msg.obj;
+
+ if (ar.exception == null) {
+ int modemNetworkMode = ((int[])ar.result)[0];
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeResponse: modemNetworkMode = "+modemNetworkMode);
+ int settingsNetworkMode = android.provider.Settings.Secure.getInt(
+ getPhone().getContext().getContentResolver(),
+ android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+ MobileNetworkSettings.preferredNetworkMode);
+
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeReponse: settingsNetworkMode = "+settingsNetworkMode);
+
+ //check that modemNetworkMode is from an accepted value
+ if (modemNetworkMode == Phone.NT_MODE_WCDMA_PREF ||
+ modemNetworkMode == Phone.NT_MODE_GSM_ONLY ||
+ modemNetworkMode == Phone.NT_MODE_WCDMA_ONLY ||
+ modemNetworkMode == Phone.NT_MODE_GSM_UMTS ||
+ modemNetworkMode == Phone.NT_MODE_CDMA ||
+ modemNetworkMode == Phone.NT_MODE_CDMA_NO_EVDO ||
+ modemNetworkMode == Phone.NT_MODE_EVDO_NO_CDMA ||
+ //A modem might report world phone sometimes
+ //but it's not true. Double check here
+ (getPhone().getContext().getResources().getBoolean(R.bool.world_phone) == true &&
+ modemNetworkMode == Phone.NT_MODE_GLOBAL) ) {
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeResponse: if 1: modemNetworkMode = "+modemNetworkMode);
+
+ //check changes in modemNetworkMode and updates settingsNetworkMode
+ if (modemNetworkMode != settingsNetworkMode) {
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeResponse: if 2: modemNetworkMode != settingsNetworkMode");
+ settingsNetworkMode = modemNetworkMode;
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeResponse: if 2: settingsNetworkMode = "+settingsNetworkMode);
+
+ //changes the Settings.System accordingly to modemNetworkMode
+ android.provider.Settings.Secure.putInt(
+ getPhone().getContext().getContentResolver(),
+ android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+ settingsNetworkMode );
+ }
+ Intent intent = new Intent(NETWORK_MODE_CHANGED);
+ intent.putExtra(NETWORK_MODE, settingsNetworkMode);
+ getPhone().getContext().sendBroadcast(intent,CHANGE_NETWORK_MODE_PERM);
+ } else if (modemNetworkMode == Phone.NT_MODE_LTE_ONLY) {
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeResponse: lte only: no action");
+ } else {
+ if (DBG) Log.d(LOG_TAG,"handleGetPreferredNetworkTypeResponse: else: reset to default");
+ resetNetworkModeToDefault();
+ }
+ }
+ }
+
+ private void handleSetPreferredNetworkTypeResponse(Message msg) {
+ //PSAFS - TODO: For now no status is stored, so we will always get the real status from Phone.
+ getPhone().getPreferredNetworkType(obtainMessage(MESSAGE_GET_PREFERRED_NETWORK_TYPE));
+ }
+
+ private void resetNetworkModeToDefault() {
+ android.provider.Settings.Secure.putInt(getPhone().getContext().getContentResolver(),
+ android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+ MobileNetworkSettings.preferredNetworkMode );
+ //Set the Modem
+ getPhone().setPreferredNetworkType(MobileNetworkSettings.preferredNetworkMode,
+ this.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE));
+ }
+ }
+}

0 comments on commit d1ca2d4

Please sign in to comment.