package com.android.systemui.statusbar.powerwidget; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; import com.android.internal.telephony.Phone; import com.android.systemui.R; public class NetworkModeButton extends PowerButton{ private static final String TAG = "NetworkModeButton"; private static final List<Uri> OBSERVED_URIS = new ArrayList<Uri>(); static { OBSERVED_URIS.add(Settings.Secure.getUriFor(Settings.Secure.PREFERRED_NETWORK_MODE)); } // retrieved from Phone.apk public static final String ACTION_NETWORK_MODE_CHANGED = "com.android.internal.telephony.NETWORK_MODE_CHANGED"; public static final String ACTION_REQUEST_NETWORK_MODE = "com.android.internal.telephony.REQUEST_NETWORK_MODE"; public static final String ACTION_MODIFY_NETWORK_MODE = "com.android.internal.telephony.MODIFY_NETWORK_MODE"; public static final String EXTRA_NETWORK_MODE = "networkMode"; private static final int NO_NETWORK_MODE_YET = -99; private static final int NETWORK_MODE_UNKNOWN = -100; private static final int CM_MODE_3G2G = 0; private static final int CM_MODE_3GONLY = 1; private static final int CM_MODE_BOTH = 2; private static int NETWORK_MODE = NO_NETWORK_MODE_YET; private static int INTENDED_NETWORK_MODE = NO_NETWORK_MODE_YET; private static int CURRENT_INTERNAL_STATE = STATE_INTERMEDIATE; public NetworkModeButton() { mType = BUTTON_NETWORKMODE; } @Override protected void updateState() { Context context = mView.getContext(); NETWORK_MODE = get2G3G(context); mState = networkModeToState(context); switch (mState) { case STATE_DISABLED: mIcon = R.drawable.stat_2g3g_off; break; case STATE_ENABLED: if (NETWORK_MODE == Phone.NT_MODE_WCDMA_ONLY) { mIcon = R.drawable.stat_3g_on; } else { mIcon = R.drawable.stat_2g3g_on; } break; case STATE_INTERMEDIATE: // In the transitional state, the bottom green bar // shows the tri-state (on, off, transitioning), but // the top dark-gray-or-bright-white logo shows the // user's intent. This is much easier to see in // sunlight. if (CURRENT_INTERNAL_STATE == STATE_TURNING_ON) { if (INTENDED_NETWORK_MODE == Phone.NT_MODE_WCDMA_ONLY) { mIcon = R.drawable.stat_3g_on; } else { mIcon = R.drawable.stat_2g3g_on; } } else { mIcon = R.drawable.stat_2g3g_off; } break; } } @Override protected void toggleState() { Context context = mView.getContext(); int currentMode = getCurrentCMMode(context); Intent intent = new Intent(ACTION_MODIFY_NETWORK_MODE); switch (NETWORK_MODE) { case Phone.NT_MODE_WCDMA_PREF: case Phone.NT_MODE_GSM_UMTS: intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_GSM_ONLY); CURRENT_INTERNAL_STATE = STATE_TURNING_OFF; INTENDED_NETWORK_MODE=Phone.NT_MODE_GSM_ONLY; break; case Phone.NT_MODE_WCDMA_ONLY: if(currentMode == CM_MODE_3GONLY) { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_GSM_ONLY); CURRENT_INTERNAL_STATE = STATE_TURNING_OFF; INTENDED_NETWORK_MODE = Phone.NT_MODE_GSM_ONLY; } else { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_PREF); CURRENT_INTERNAL_STATE = STATE_TURNING_ON; INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_PREF; } break; case Phone.NT_MODE_GSM_ONLY: if(currentMode == CM_MODE_3GONLY || currentMode == CM_MODE_BOTH) { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_ONLY); CURRENT_INTERNAL_STATE = STATE_TURNING_ON; INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_ONLY; } else { intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_PREF); CURRENT_INTERNAL_STATE = STATE_TURNING_ON; INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_PREF; } break; } NETWORK_MODE = NETWORK_MODE_UNKNOWN; context.sendBroadcast(intent); } @Override protected boolean handleLongClick() { // it may be better to make an Intent action for this or find the appropriate one // we may want to look at that option later Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName("com.android.phone", "com.android.phone.Settings"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mView.getContext().startActivity(intent); return true; } @Override public void onReceive(Context context, Intent intent) { if (intent.getExtras() != null) { NETWORK_MODE = intent.getExtras().getInt(EXTRA_NETWORK_MODE); //Update to actual state INTENDED_NETWORK_MODE = NETWORK_MODE; } //need to clear intermediate states CURRENT_INTERNAL_STATE = STATE_ENABLED; int widgetState = networkModeToState(context); CURRENT_INTERNAL_STATE = widgetState; if (widgetState == STATE_ENABLED) { MobileDataButton mdb = (MobileDataButton)getLoadedButton(BUTTON_MOBILEDATA); if(mdb != null) { mdb.networkModeChanged(context, NETWORK_MODE); } } } @Override protected IntentFilter getBroadcastIntentFilter() { IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_NETWORK_MODE_CHANGED); return filter; } @Override protected List<Uri> getObservedUris() { return OBSERVED_URIS; } private static int get2G3G(Context context) { int state = 99; try { state = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.PREFERRED_NETWORK_MODE); } catch (SettingNotFoundException e) { } return state; } private static int networkModeToState(Context context) { if (CURRENT_INTERNAL_STATE == STATE_TURNING_ON || CURRENT_INTERNAL_STATE == STATE_TURNING_OFF) return STATE_INTERMEDIATE; switch(NETWORK_MODE) { case Phone.NT_MODE_WCDMA_PREF: case Phone.NT_MODE_WCDMA_ONLY: case Phone.NT_MODE_GSM_UMTS: return STATE_ENABLED; case Phone.NT_MODE_GSM_ONLY: return STATE_DISABLED; case Phone.NT_MODE_CDMA: case Phone.NT_MODE_CDMA_NO_EVDO: case Phone.NT_MODE_EVDO_NO_CDMA: case Phone.NT_MODE_GLOBAL: // need to check wtf is going on Log.d(TAG, "Unexpected network mode (" + NETWORK_MODE + ")"); return STATE_DISABLED; } return STATE_INTERMEDIATE; } private static int getCurrentCMMode(Context context) { return Settings.System.getInt(context.getContentResolver(), Settings.System.EXPANDED_NETWORK_MODE, CM_MODE_3G2G); } }