org.sipdroid.sipua.ui.Receiver.java Source code

Java tutorial

Introduction

Here is the source code for org.sipdroid.sipua.ui.Receiver.java

Source

/*
 * Copyright (C) 2009 The Sipdroid Open Source Project
 * 
 * This file is part of Sipdroid (http://www.sipdroid.org)
 * 
 * Sipdroid is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This source code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this source code; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.sipdroid.sipua.ui;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;

import android.app.AlarmManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.app.NotificationCompat;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;

import org.sipdroid.media.Bluetooth;
import org.sipdroid.media.RtpStreamReceiver;
import org.sipdroid.media.RtpStreamSender;
import org.sipdroid.sipua.*;
import org.sipdroid.sipua.phone.Call;
import org.sipdroid.sipua.phone.Connection;
import org.zoolu.sip.provider.SipProvider;

public class Receiver extends BroadcastReceiver {

    final static String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
    final static String ACTION_SIGNAL_STRENGTH_CHANGED = "android.intent.action.SIG_STR";
    final static String ACTION_DATA_STATE_CHANGED = "android.intent.action.ANY_DATA_STATE";
    final static String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
    final static String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
    final static String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
    final static String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE";
    final static String PAUSE_ACTION = "com.android.music.musicservicecommand.pause";
    final static String TOGGLEPAUSE_ACTION = "com.android.music.musicservicecommand.togglepause";
    final static String ACTION_DEVICE_IDLE = "com.android.server.WifiManager.action.DEVICE_IDLE";
    final static String ACTION_VPN_CONNECTIVITY = "vpn.connectivity";
    final static String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
    final static String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
    final static String METADATA_DOCK_HOME = "android.dock_home";
    final static String CATEGORY_DESK_DOCK = "android.intent.category.DESK_DOCK";
    final static String CATEGORY_CAR_DOCK = "android.intent.category.CAR_DOCK";
    final static int EXTRA_DOCK_STATE_DESK = 1;
    final static int EXTRA_DOCK_STATE_CAR = 2;

    public final static int MWI_NOTIFICATION = 1;
    public final static int CALL_NOTIFICATION = 2;
    public final static int MISSED_CALL_NOTIFICATION = 3;
    public final static int AUTO_ANSWER_NOTIFICATION = 4;
    public final static int REGISTER_NOTIFICATION = 5;

    final static int MSG_SCAN = 1;
    final static int MSG_ENABLE = 2;
    final static int MSG_HOLD = 3;
    final static int MSG_HANGUP = 4;

    final static long[] vibratePattern = { 0, 1000, 1000 };

    public static int docked = -1, headset = -1, bluetooth = -1;
    public static SipdroidEngine mSipdroidEngine;

    public static Context mContext;
    public static SipdroidListener listener_video;
    public static Call ccCall;
    public static Connection ccConn;
    public static int call_state;
    public static int call_end_reason = -1;

    public static String pstn_state;
    public static long pstn_time;
    public static String MWI_account;
    private static String laststate, lastnumber;

    public static synchronized SipdroidEngine engine(Context context) {
        if (mContext == null || !context.getClass().getName().contains("ReceiverRestrictedContext"))
            mContext = context;
        if (mSipdroidEngine == null) {
            if (android.os.Build.VERSION.SDK_INT > 9) {
                ReceiverNew.setPolicy();
            }
            mSipdroidEngine = new SipdroidEngine();
            mSipdroidEngine.StartEngine();
            if (Integer.parseInt(Build.VERSION.SDK) >= 8)
                Bluetooth.init();
        } else
            mSipdroidEngine.CheckEngine();
        context.startService(new Intent(context, RegisterService.class));
        return mSipdroidEngine;
    }

    public static Ringtone oRingtone;
    static PowerManager.WakeLock wl;

    public static void stopRingtone() {
        if (v != null)
            v.cancel();
        if (Receiver.oRingtone != null) {
            Ringtone ringtone = Receiver.oRingtone;
            oRingtone = null;
            ringtone.stop();
        }
    }

    static android.os.Vibrator v;

    public static void onState(int state, String caller) {
        if (ccCall == null) {
            ccCall = new Call();
            ccConn = new Connection();
            ccCall.setConn(ccConn);
            ccConn.setCall(ccCall);
        }
        if (call_state != state) {
            if (state != UserAgent.UA_STATE_IDLE)
                call_end_reason = -1;
            call_state = state;
            switch (call_state) {
            case UserAgent.UA_STATE_INCOMING_CALL:
                enable_wifi(true);
                RtpStreamReceiver.good = RtpStreamReceiver.lost = RtpStreamReceiver.loss = RtpStreamReceiver.late = 0;
                RtpStreamReceiver.speakermode = speakermode();
                bluetooth = -1;
                String text = caller.toString();
                if (text.indexOf("<sip:") >= 0 && text.indexOf("@") >= 0)
                    text = text.substring(text.indexOf("<sip:") + 5, text.indexOf("@"));
                String text2 = caller.toString();
                if (text2.indexOf("\"") >= 0)
                    text2 = text2.substring(text2.indexOf("\"") + 1, text2.lastIndexOf("\""));
                broadcastCallStateChanged("RINGING", caller);
                mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
                ccCall.setState(Call.State.INCOMING);
                ccConn.setUserData(null);
                ccConn.setAddress(text, text2);
                ccConn.setIncoming(true);
                ccConn.date = System.currentTimeMillis();
                ccCall.base = 0;
                AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
                int rm = am.getRingerMode();
                int vs = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
                KeyguardManager mKeyguardManager = (KeyguardManager) mContext
                        .getSystemService(Context.KEYGUARD_SERVICE);
                if (v == null)
                    v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
                if ((pstn_state == null || pstn_state.equals("IDLE"))
                        && PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                                org.sipdroid.sipua.ui.Settings.PREF_AUTO_ON,
                                org.sipdroid.sipua.ui.Settings.DEFAULT_AUTO_ON)
                        && !mKeyguardManager.inKeyguardRestrictedInputMode())
                    v.vibrate(vibratePattern, 1);
                else {
                    if ((pstn_state == null || pstn_state.equals("IDLE")) && (rm == AudioManager.RINGER_MODE_VIBRATE
                            || (rm == AudioManager.RINGER_MODE_NORMAL && vs == AudioManager.VIBRATE_SETTING_ON)))
                        v.vibrate(vibratePattern, 1);
                    if (am.getStreamVolume(AudioManager.STREAM_RING) > 0) {
                        String sUriSipRingtone = PreferenceManager.getDefaultSharedPreferences(mContext).getString(
                                org.sipdroid.sipua.ui.Settings.PREF_SIPRINGTONE,
                                Settings.System.DEFAULT_RINGTONE_URI.toString());
                        if (!TextUtils.isEmpty(sUriSipRingtone)) {
                            oRingtone = RingtoneManager.getRingtone(mContext, Uri.parse(sUriSipRingtone));
                            if (oRingtone != null)
                                oRingtone.play();
                        }
                    }
                }
                moveTop();
                if (wl == null) {
                    PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
                    wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
                            "Sipdroid.onState");
                }
                wl.acquire();
                Checkin.checkin(true);
                break;
            case UserAgent.UA_STATE_OUTGOING_CALL:
                RtpStreamReceiver.good = RtpStreamReceiver.lost = RtpStreamReceiver.loss = RtpStreamReceiver.late = 0;
                RtpStreamReceiver.speakermode = speakermode();
                bluetooth = -1;
                onText(MISSED_CALL_NOTIFICATION, null, 0, 0);
                engine(mContext).register();
                broadcastCallStateChanged("OFFHOOK", caller);
                ccCall.setState(Call.State.DIALING);
                ccConn.setUserData(null);
                ccConn.setAddress(caller, caller);
                ccConn.setIncoming(false);
                ccConn.date = System.currentTimeMillis();
                ccCall.base = 0;
                moveTop();
                Checkin.checkin(true);
                break;
            case UserAgent.UA_STATE_IDLE:
                broadcastCallStateChanged("IDLE", null);
                onText(CALL_NOTIFICATION, null, 0, 0);
                ccCall.setState(Call.State.DISCONNECTED);
                if (listener_video != null)
                    listener_video.onHangup();
                stopRingtone();
                if (wl != null && wl.isHeld())
                    wl.release();
                mContext.startActivity(createIntent(InCallScreen.class));
                ccConn.log(ccCall.base);
                ccConn.date = 0;
                engine(mContext).listen();
                break;
            case UserAgent.UA_STATE_INCALL:
                broadcastCallStateChanged("OFFHOOK", null);
                if (ccCall.base == 0) {
                    ccCall.base = SystemClock.elapsedRealtime();
                }
                progress();
                ccCall.setState(Call.State.ACTIVE);
                stopRingtone();
                if (wl != null && wl.isHeld())
                    wl.release();
                mContext.startActivity(createIntent(InCallScreen.class));
                break;
            case UserAgent.UA_STATE_HOLD:
                onText(CALL_NOTIFICATION, mContext.getString(R.string.card_title_on_hold),
                        android.R.drawable.stat_sys_phone_call_on_hold, ccCall.base);
                ccCall.setState(Call.State.HOLDING);
                if (InCallScreen.started && (pstn_state == null || !pstn_state.equals("RINGING")))
                    mContext.startActivity(createIntent(InCallScreen.class));
                break;
            }
            pos(true);
            RtpStreamReceiver.ringback(false);
        }
    }

    static String cache_text;
    static int cache_res;

    public static void onText(int type, String text, int mInCallResId, long base) {
        if (mSipdroidEngine != null && type == REGISTER_NOTIFICATION + mSipdroidEngine.pref) {
            cache_text = text;
            cache_res = mInCallResId;
        }
        if (type >= REGISTER_NOTIFICATION && mInCallResId == R.drawable.sym_presence_available
                && !PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean(
                        org.sipdroid.sipua.ui.Settings.PREF_REGISTRATION,
                        org.sipdroid.sipua.ui.Settings.DEFAULT_REGISTRATION))
            text = null;
        NotificationManager mNotificationMgr = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        if (text != null) {
            Notification notification = new Notification();
            NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);

            notification.icon = mInCallResId;
            if (type == MISSED_CALL_NOTIFICATION) {
                notification.flags |= Notification.FLAG_AUTO_CANCEL;
                //TODO
                /*notification.setLatestEventInfo(mContext, text, mContext.getString(R.string.app_name),
                      PendingIntent.getActivity(mContext, 0, createCallLogIntent(), 0));
                if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean(org.sipdroid.sipua.ui.Settings.PREF_NOTIFY, org.sipdroid.sipua.ui.Settings.DEFAULT_NOTIFY)) {
                   notification.flags |= Notification.FLAG_SHOW_LIGHTS;
                   notification.ledARGB = 0xff0000ff;  blue 
                   notification.ledOnMS = 125;
                   notification.ledOffMS = 2875;
                }*/
            } else {
                switch (type) {
                case MWI_NOTIFICATION:
                    notification.flags |= Notification.FLAG_AUTO_CANCEL;
                    notification.contentIntent = PendingIntent.getActivity(mContext, 0, createMWIIntent(), 0);
                    notification.flags |= Notification.FLAG_SHOW_LIGHTS;
                    notification.ledARGB = 0xff00ff00; /* green */
                    notification.ledOnMS = 125;
                    notification.ledOffMS = 2875;
                    break;
                case AUTO_ANSWER_NOTIFICATION:
                    notification.contentIntent = PendingIntent.getActivity(mContext, 0,
                            createIntent(AutoAnswer.class), 0);
                    break;
                default:
                    if (type >= REGISTER_NOTIFICATION && mSipdroidEngine != null
                            && type != REGISTER_NOTIFICATION + mSipdroidEngine.pref
                            && mInCallResId == R.drawable.sym_presence_available) {
                        int key = type - REGISTER_NOTIFICATION;
                        Intent in = createIntent(ChangeAccount.class);
                        in.setAction(Long.toString(type));
                        in.putExtra(ChangeAccount.ChangeAccountKey, key);
                        in.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
                        notification.contentIntent = PendingIntent.getActivity(mContext, key, in,
                                PendingIntent.FLAG_UPDATE_CURRENT);
                    } else
                        notification.contentIntent = PendingIntent.getActivity(mContext, 0,
                                createIntent(Sipdroid.class), 0);
                    if (mInCallResId == R.drawable.sym_presence_away) {
                        notification.flags |= Notification.FLAG_SHOW_LIGHTS;
                        notification.ledARGB = 0xffff0000; /* red */
                        notification.ledOnMS = 125;
                        notification.ledOffMS = 2875;
                    }
                    notification.flags |= Notification.FLAG_ONGOING_EVENT;
                    break;
                }

                RemoteViews contentView = new RemoteViews(mContext.getPackageName(),
                        R.layout.ongoing_call_notification);
                contentView.setImageViewResource(R.id.icon, notification.icon);
                if (base != 0) {
                    contentView.setChronometer(R.id.text1, base, text + " (%s)", true);
                } else if (type >= REGISTER_NOTIFICATION) {
                    if (PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                            org.sipdroid.sipua.ui.Settings.PREF_POS, org.sipdroid.sipua.ui.Settings.DEFAULT_POS))
                        contentView.setTextViewText(R.id.text2,
                                text + "/" + mContext.getString(R.string.settings_pos3));
                    else
                        contentView.setTextViewText(R.id.text2, text);
                    if (mSipdroidEngine != null)
                        contentView.setTextViewText(R.id.text1,
                                mSipdroidEngine.user_profiles[type - REGISTER_NOTIFICATION].username + "@"
                                        + mSipdroidEngine.user_profiles[type - REGISTER_NOTIFICATION].realm_orig);
                } else
                    contentView.setTextViewText(R.id.text1, text);
                notification.contentView = contentView;
            }
            mNotificationMgr.notify(type, notification);
        } else {
            mNotificationMgr.cancel(type);
        }
        if (type != AUTO_ANSWER_NOTIFICATION)
            updateAutoAnswer();
        if (mSipdroidEngine != null && type >= REGISTER_NOTIFICATION
                && type != REGISTER_NOTIFICATION + mSipdroidEngine.pref)
            onText(REGISTER_NOTIFICATION + mSipdroidEngine.pref, cache_text, cache_res, 0);
    }

    static void updateAutoAnswer() {
        if (PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                org.sipdroid.sipua.ui.Settings.PREF_AUTO_ONDEMAND,
                org.sipdroid.sipua.ui.Settings.DEFAULT_AUTO_ONDEMAND) && Sipdroid.on(mContext)) {
            if (PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_AUTO_DEMAND,
                    org.sipdroid.sipua.ui.Settings.DEFAULT_AUTO_DEMAND))
                updateAutoAnswer(1);
            else
                updateAutoAnswer(0);
        } else
            updateAutoAnswer(-1);
    }

    private static int autoAnswerState = -1;

    static void updateAutoAnswer(int status) {
        if (status != autoAnswerState) {
            switch (autoAnswerState = status) {
            case 0:
                Receiver.onText(Receiver.AUTO_ANSWER_NOTIFICATION, mContext.getString(R.string.auto_disabled),
                        R.drawable.auto_answer_disabled, 0);
                break;
            case 1:
                Receiver.onText(Receiver.AUTO_ANSWER_NOTIFICATION, mContext.getString(R.string.auto_enabled),
                        R.drawable.auto_answer, 0);
                break;
            case -1:
                Receiver.onText(Receiver.AUTO_ANSWER_NOTIFICATION, null, 0, 0);
                break;
            }
        }
    }

    public static void registered() {
        pos(true);
    }

    static LocationManager lm;
    static AlarmManager am;
    static PendingIntent gps_sender, net_sender;
    static boolean net_enabled;
    static long loctrydate;

    static final int GPS_UPDATES = 4000 * 1000;
    static final int NET_UPDATES = 600 * 1000;

    public static void pos(boolean enable) {

        if (!PreferenceManager.getDefaultSharedPreferences(mContext)
                .getBoolean(org.sipdroid.sipua.ui.Settings.PREF_POS, org.sipdroid.sipua.ui.Settings.DEFAULT_POS)
                || PreferenceManager.getDefaultSharedPreferences(mContext)
                        .getString(org.sipdroid.sipua.ui.Settings.PREF_POSURL,
                                org.sipdroid.sipua.ui.Settings.DEFAULT_POSURL)
                        .length() < 1) {
            if (lm != null && am != null) {
                pos_gps(false);
                pos_net(false);
                lm = null;
                am = null;
            }
            return;
        }

        if (lm == null)
            lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        if (am == null)
            am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        pos_gps(false);
        if (enable) {
            if (call_state == UserAgent.UA_STATE_IDLE && Sipdroid.on(mContext)
                    && PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                            org.sipdroid.sipua.ui.Settings.PREF_POS, org.sipdroid.sipua.ui.Settings.DEFAULT_POS)
                    && PreferenceManager.getDefaultSharedPreferences(mContext)
                            .getString(org.sipdroid.sipua.ui.Settings.PREF_POSURL,
                                    org.sipdroid.sipua.ui.Settings.DEFAULT_POSURL)
                            .length() > 0) {
                Location last = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                if (System.currentTimeMillis() - loctrydate > GPS_UPDATES
                        && (last == null || System.currentTimeMillis() - last.getTime() > GPS_UPDATES)) {
                    loctrydate = System.currentTimeMillis();
                    pos_gps(true);
                    pos_net(false);
                } else if (last != null)
                    Receiver.url("lat=" + last.getLatitude() + "&lon=" + last.getLongitude() + "&rad="
                            + last.getAccuracy());
                pos_net(true);
            } else
                pos_net(false);
        }
    }

    static void pos_gps(boolean enable) {
        if (gps_sender == null) {
            Intent intent = new Intent(mContext, OneShotLocation.class);
            gps_sender = PendingIntent.getBroadcast(mContext, 0, intent, 0);
        }
        if (enable) {
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATES, 3000, gps_sender);
            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 10 * 1000, gps_sender);
        } else {
            am.cancel(gps_sender);
            lm.removeUpdates(gps_sender);
        }
    }

    static void pos_net(boolean enable) {
        if (net_sender == null) {
            Intent loopintent = new Intent(mContext, LoopLocation.class);
            net_sender = PendingIntent.getBroadcast(mContext, 0, loopintent, 0);
        }
        if (net_enabled != enable) {
            if (enable) {
                lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, NET_UPDATES, 3000, net_sender);
            } else {
                lm.removeUpdates(net_sender);
            }
            net_enabled = enable;
        }
    }

    static void enable_wifi(boolean enable) {
        if (!PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                org.sipdroid.sipua.ui.Settings.PREF_OWNWIFI, org.sipdroid.sipua.ui.Settings.DEFAULT_OWNWIFI))
            return;
        if (enable && !PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                org.sipdroid.sipua.ui.Settings.PREF_WIFI_DISABLED,
                org.sipdroid.sipua.ui.Settings.DEFAULT_WIFI_DISABLED))
            return;
        WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        ContentResolver cr = Receiver.mContext.getContentResolver();
        if (!enable && Settings.Secure.getInt(cr, Settings.Secure.WIFI_ON, 0) == 0)
            return;
        Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();

        edit.putBoolean(org.sipdroid.sipua.ui.Settings.PREF_WIFI_DISABLED, !enable);
        edit.commit();
        /*
        if (enable) {
            Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
            intent.putExtra(WifiManager.EXTRA_NEW_STATE, wm.getWifiState());
            mContext.sendBroadcast(intent);
        }
        */
        wm.setWifiEnabled(enable);
    }

    public static void url(final String opt) {
        (new Thread() {
            public void run() {
                try {
                    URL url = new URL(PreferenceManager.getDefaultSharedPreferences(mContext).getString(
                            org.sipdroid.sipua.ui.Settings.PREF_POSURL,
                            org.sipdroid.sipua.ui.Settings.DEFAULT_POSURL) + "?" + opt);
                    BufferedReader in;
                    in = new BufferedReader(new InputStreamReader(url.openStream()));
                    in.close();
                } catch (IOException e) {
                    if (!Sipdroid.release)
                        e.printStackTrace();
                }

            }
        }).start();
    }

    static boolean was_playing;

    static void broadcastCallStateChanged(String state, String number) {
        if (state == null) {
            state = laststate;
            number = lastnumber;
        }
        if (android.os.Build.VERSION.SDK_INT < 19) {
            Intent intent = new Intent(ACTION_PHONE_STATE_CHANGED);
            intent.putExtra("state", state);
            if (number != null)
                intent.putExtra("incoming_number", number);
            intent.putExtra(mContext.getString(R.string.app_name), true);
            mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
        }
        if (state.equals("IDLE")) {
            if (was_playing) {
                if (pstn_state == null || pstn_state.equals("IDLE"))
                    mContext.sendBroadcast(new Intent(TOGGLEPAUSE_ACTION));
                was_playing = false;
            }
        } else {
            AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
            if ((laststate == null || laststate.equals("IDLE")) && (was_playing = am.isMusicActive()))
                mContext.sendBroadcast(new Intent(PAUSE_ACTION));
        }
        laststate = state;
        lastnumber = number;
    }

    public static void alarm(int renew_time, Class<?> cls) {
        if (!Sipdroid.release)
            Log.i("SipUA:", "alarm " + renew_time);
        Intent intent = new Intent(mContext, cls);
        PendingIntent sender = PendingIntent.getBroadcast(mContext, 0, intent, 0);
        AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        am.cancel(sender);
        if (renew_time > 0)
            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + renew_time * 1000, sender);
    }

    public static long expire_time;

    public static synchronized void reRegister(int renew_time) {
        if (renew_time == 0)
            expire_time = 0;
        else {
            if (expire_time != 0 && renew_time * 1000 + SystemClock.elapsedRealtime() > expire_time)
                return;
            expire_time = renew_time * 1000 + SystemClock.elapsedRealtime();
        }
        alarm(renew_time - 15, OneShotAlarm.class);
    }

    static Intent createIntent(Class<?> cls) {
        Intent startActivity = new Intent();
        startActivity.setClass(mContext, cls);
        startActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return startActivity;
    }

    public static Intent createCallLogIntent() {
        Intent intent = new Intent(Intent.ACTION_VIEW, null);
        intent.setType("vnd.android.cursor.dir/calls");
        return intent;
    }

    static Intent createHomeDockIntent() {
        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        if (docked == EXTRA_DOCK_STATE_CAR) {
            intent.addCategory(CATEGORY_CAR_DOCK);
        } else if (docked == EXTRA_DOCK_STATE_DESK) {
            intent.addCategory(CATEGORY_DESK_DOCK);
        } else {
            return null;
        }

        ActivityInfo ai = intent.resolveActivityInfo(mContext.getPackageManager(), PackageManager.GET_META_DATA);
        if (ai == null) {
            return null;
        }

        if (ai.metaData != null && ai.metaData.getBoolean(METADATA_DOCK_HOME)) {
            intent.setClassName(ai.packageName, ai.name);
            return intent;
        }

        return null;
    }

    public static Intent createHomeIntent() {
        Intent intent = createHomeDockIntent();
        if (intent != null) {
            try {
                return intent;
            } catch (ActivityNotFoundException e) {
            }
        }
        intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_HOME);
        return intent;
    }

    static Intent createMWIIntent() {
        Intent intent;

        if (MWI_account != null)
            intent = new Intent(Intent.ACTION_CALL, Uri.parse(MWI_account.replaceFirst("sip:", "sipdroid:")));
        else
            intent = new Intent(Intent.ACTION_DIAL);
        return intent;
    }

    public static void moveTop() {
        progress();
        mContext.startActivity(createIntent(Activity2.class));
    }

    public static void progress() {
        if (call_state == UserAgent.UA_STATE_IDLE)
            return;
        int mode = RtpStreamReceiver.speakermode;
        if (mode == -1)
            mode = speakermode();
        if (mode == AudioManager.MODE_NORMAL)
            Receiver.onText(Receiver.CALL_NOTIFICATION, mContext.getString(R.string.menu_speaker),
                    android.R.drawable.stat_sys_speakerphone, Receiver.ccCall.base);
        else if (bluetooth > 0)
            Receiver.onText(Receiver.CALL_NOTIFICATION, mContext.getString(R.string.menu_bluetooth),
                    R.drawable.stat_sys_phone_call_bluetooth, Receiver.ccCall.base);
        else
            Receiver.onText(Receiver.CALL_NOTIFICATION, mContext.getString(R.string.card_title_in_progress),
                    R.drawable.stat_sys_phone_call, Receiver.ccCall.base);
    }

    public static boolean on_wlan;

    static boolean on_vpn() {
        return PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                org.sipdroid.sipua.ui.Settings.PREF_ON_VPN, org.sipdroid.sipua.ui.Settings.DEFAULT_ON_VPN);
    }

    static void on_vpn(boolean enable) {
        Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();

        edit.putBoolean(org.sipdroid.sipua.ui.Settings.PREF_ON_VPN, enable);
        edit.commit();
    }

    public static boolean isFast(int i) {
        WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        WifiInfo wi = wm.getConnectionInfo();

        if (PreferenceManager.getDefaultSharedPreferences(mContext)
                .getString(org.sipdroid.sipua.ui.Settings.PREF_USERNAME + (i != 0 ? i : ""), "").equals("")
                || PreferenceManager.getDefaultSharedPreferences(mContext)
                        .getString(org.sipdroid.sipua.ui.Settings.PREF_SERVER + (i != 0 ? i : ""), "").equals(""))
            return false;
        if (wi != null) {
            if (!Sipdroid.release)
                Log.i("SipUA:", "isFastWifi() " + WifiInfo.getDetailedStateOf(wi.getSupplicantState()) + " "
                        + wi.getIpAddress());
            if (wi.getIpAddress() != 0
                    && (WifiInfo.getDetailedStateOf(wi.getSupplicantState()) == DetailedState.OBTAINING_IPADDR
                            || WifiInfo.getDetailedStateOf(wi.getSupplicantState()) == DetailedState.CONNECTED)
                    || WifiInfo.getDetailedStateOf(wi.getSupplicantState()) == DetailedState.CONNECTING) {
                on_wlan = true;
                if (!on_vpn())
                    return PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                            org.sipdroid.sipua.ui.Settings.PREF_WLAN + (i != 0 ? i : ""),
                            org.sipdroid.sipua.ui.Settings.DEFAULT_WLAN);
                else
                    return PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                            org.sipdroid.sipua.ui.Settings.PREF_VPN + (i != 0 ? i : ""),
                            org.sipdroid.sipua.ui.Settings.DEFAULT_VPN);
            }
        }
        on_wlan = false;
        return isFastGSM(i);
    }

    static boolean isFastGSM(int i) {
        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

        if (Sipdroid.market)
            return false;
        if (on_vpn() && (tm.getNetworkType() >= TelephonyManager.NETWORK_TYPE_EDGE))
            return PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_VPN + (i != 0 ? i : ""),
                    org.sipdroid.sipua.ui.Settings.DEFAULT_VPN);
        if (tm.getNetworkType() >= TelephonyManager.NETWORK_TYPE_UMTS)
            return PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_3G + (i != 0 ? i : ""),
                    org.sipdroid.sipua.ui.Settings.DEFAULT_3G);
        if (tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_EDGE)
            return PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_EDGE + (i != 0 ? i : ""),
                    org.sipdroid.sipua.ui.Settings.DEFAULT_EDGE);
        return false;
    }

    public static int speakermode() {
        if (docked > 0 && headset <= 0)
            return AudioManager.MODE_NORMAL;
        else
            return AudioManager.MODE_IN_CALL;
    }

    static Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_SCAN:
                WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
                wm.startScan();
                break;
            case MSG_ENABLE:
                enable_wifi(true);
                break;
            case MSG_HOLD:
                engine(mContext).togglehold();
                break;
            case MSG_HANGUP:
                engine(mContext).rejectcall();
                break;
            }
        }
    };

    int asu(ScanResult scan) {
        if (scan == null)
            return 0;
        return Math.round((scan.level + 113f) / 2f);
    }

    static long lastscan;

    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (!Sipdroid.on(context))
            return;
        if (!Sipdroid.release)
            Log.i("SipUA:", intentAction);
        if (mContext == null)
            mContext = context;
        if (intentAction.equals(Intent.ACTION_BOOT_COMPLETED)) {
            on_vpn(false);
            engine(context).register();
        } else if (intentAction.equals(ConnectivityManager.CONNECTIVITY_ACTION)
                || intentAction.equals(ACTION_EXTERNAL_APPLICATIONS_AVAILABLE)
                || intentAction.equals(ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)
                || intentAction.equals(Intent.ACTION_PACKAGE_REPLACED)) {
            engine(context).register();
        } else if (intentAction.equals(ACTION_VPN_CONNECTIVITY) && intent.hasExtra("connection_state")) {
            String state = intent.getSerializableExtra("connection_state").toString();
            if (state != null && on_vpn() != state.equals("CONNECTED")) {
                on_vpn(state.equals("CONNECTED"));
                for (SipProvider sip_provider : engine(context).sip_providers)
                    if (sip_provider != null)
                        sip_provider.haltConnections();
                engine(context).register();
            }
        } else if (intentAction.equals(ACTION_DATA_STATE_CHANGED)) {
            engine(context).registerMore();
        } else if (intentAction.equals(ACTION_PHONE_STATE_CHANGED)
                && !intent.getBooleanExtra(context.getString(R.string.app_name), false)) {
            stopRingtone();
            pstn_state = intent.getStringExtra("state");
            pstn_time = SystemClock.elapsedRealtime();
            if (pstn_state.equals("IDLE") && call_state != UserAgent.UA_STATE_IDLE)
                broadcastCallStateChanged(null, null);
            if (!pstn_state.equals("IDLE") && call_state == UserAgent.UA_STATE_INCALL)
                mHandler.sendEmptyMessageDelayed(MSG_HOLD, 5000);
            else if (!pstn_state.equals("IDLE") && (call_state == UserAgent.UA_STATE_INCOMING_CALL
                    || call_state == UserAgent.UA_STATE_OUTGOING_CALL))
                mHandler.sendEmptyMessageDelayed(MSG_HANGUP, 5000);
            else if (pstn_state.equals("IDLE")) {
                mHandler.removeMessages(MSG_HOLD);
                mHandler.removeMessages(MSG_HANGUP);
                if (call_state == UserAgent.UA_STATE_HOLD)
                    mHandler.sendEmptyMessageDelayed(MSG_HOLD, 1000);
            }
        } else if (intentAction.equals(ACTION_DOCK_EVENT)) {
            docked = intent.getIntExtra(EXTRA_DOCK_STATE, -1) & 7;
            if (call_state == UserAgent.UA_STATE_INCALL)
                engine(mContext).speaker(speakermode());
        } else if (intentAction.equals(ACTION_SCO_AUDIO_STATE_CHANGED)) {
            bluetooth = intent.getIntExtra(EXTRA_SCO_AUDIO_STATE, -1);
            progress();
            RtpStreamSender.changed = true;
        } else if (intentAction.equals(Intent.ACTION_HEADSET_PLUG)) {
            headset = intent.getIntExtra("state", -1);
            if (call_state == UserAgent.UA_STATE_INCALL)
                engine(mContext).speaker(speakermode());
        } else if (intentAction.equals(Intent.ACTION_SCREEN_ON)) {
            if (!PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_OWNWIFI, org.sipdroid.sipua.ui.Settings.DEFAULT_OWNWIFI))
                alarm(0, OwnWifi.class);
        } else if (intentAction.equals(Intent.ACTION_USER_PRESENT)) {
            mHandler.sendEmptyMessageDelayed(MSG_ENABLE, 3000);
        } else if (intentAction.equals(Intent.ACTION_SCREEN_OFF)) {
            if (PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_OWNWIFI, org.sipdroid.sipua.ui.Settings.DEFAULT_OWNWIFI)) {
                WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wi = wm.getConnectionInfo();
                if (wm.getWifiState() != WifiManager.WIFI_STATE_ENABLED || wi == null
                        || wi.getSupplicantState() != SupplicantState.COMPLETED || wi.getIpAddress() == 0)
                    alarm(2 * 60, OwnWifi.class);
                else
                    alarm(15 * 60, OwnWifi.class);
            }
            if (SipdroidEngine.pwl != null)
                for (PowerManager.WakeLock pwl : SipdroidEngine.pwl)
                    if (pwl != null && pwl.isHeld()) {
                        pwl.release();
                        pwl.acquire();
                    }
        } else if (intentAction.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
            if (PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                    org.sipdroid.sipua.ui.Settings.PREF_SELECTWIFI,
                    org.sipdroid.sipua.ui.Settings.DEFAULT_SELECTWIFI))
                mHandler.sendEmptyMessageDelayed(MSG_SCAN, 3000);
        } else if (intentAction.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
            if (SystemClock.uptimeMillis() > lastscan + 45000
                    && PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(
                            org.sipdroid.sipua.ui.Settings.PREF_SELECTWIFI,
                            org.sipdroid.sipua.ui.Settings.DEFAULT_SELECTWIFI)) {
                WifiManager wm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wi = wm.getConnectionInfo();
                String activeSSID = null;
                if (wi != null)
                    activeSSID = wi.getSSID();
                if (activeSSID != null && (activeSSID.length() == 0 || activeSSID.equals("0x")))
                    activeSSID = null;
                List<ScanResult> mScanResults = wm.getScanResults();
                List<WifiConfiguration> configurations = wm.getConfiguredNetworks();
                if (configurations != null) {
                    WifiConfiguration bestconfig = null, maxconfig = null, activeconfig = null;
                    for (final WifiConfiguration config : configurations) {
                        if (maxconfig == null || config.priority > maxconfig.priority) {
                            maxconfig = config;
                        }
                        if (config.SSID != null
                                && (config.SSID.equals("\"" + activeSSID + "\"") || config.SSID.equals(activeSSID)))
                            activeconfig = config;
                    }
                    ScanResult bestscan = null, activescan = null;
                    if (mScanResults != null)
                        for (final ScanResult scan : mScanResults) {
                            for (final WifiConfiguration config : configurations) {
                                if (config.SSID != null && config.SSID.equals("\"" + scan.SSID + "\"")) {
                                    if (bestscan == null || scan.level > bestscan.level) {
                                        bestscan = scan;
                                        bestconfig = config;
                                    }
                                    if (config == activeconfig)
                                        activescan = scan;
                                }
                            }
                        }
                    if (activescan != null)
                        System.out.println("debug wifi asu(active)" + asu(activescan));
                    if (bestconfig != null && (activeconfig == null || bestconfig.priority != activeconfig.priority)
                            && asu(bestscan) > asu(activescan) * 1.5 &&
                            /* (activeSSID == null || activescan != null) && */ asu(bestscan) > 22) {
                        if (!Sipdroid.release)
                            Log.i("SipUA:", "changing to " + bestconfig.SSID);
                        if (activeSSID == null || !activeSSID.equals(bestscan.SSID))
                            wm.disconnect();
                        bestconfig.priority = maxconfig.priority + 1;
                        wm.updateNetwork(bestconfig);
                        wm.enableNetwork(bestconfig.networkId, true);
                        wm.saveConfiguration();
                        if (activeSSID == null || !activeSSID.equals(bestscan.SSID))
                            wm.reconnect();
                        lastscan = SystemClock.uptimeMillis();
                    } else if (activescan != null && asu(activescan) < 15) {
                        wm.disconnect();
                        wm.disableNetwork(activeconfig.networkId);
                        wm.saveConfiguration();
                    }
                }
            }
        }
    }
}