public static final int INTERVAL_ONE_MONTH = 3; public static final int INTERVAL_ONE_WEEK = 2; public static final int INTERVAL_TODAY = 1; public static final String SP_KEY_TIME_INTERVAL = "pref_time_interval"; public static final String SP_NAME = "netstat"; public static final String TAG = "FreeMobileNetstat"; public class Event {
    public long timestamp;
    public boolean screenOn;
    public boolean wifiConnected;
    public boolean mobileConnected;
    public String mobileOperator;
    public int batteryLevel;
    public boolean powerOn;

    /**
     * Read an {@link Event} instance from a database {@link Cursor}. The cursor
     * should include every columns defined in {@link Events}.
     */
    public void read(Cursor c) {
        timestamp = c.getLong(c.getColumnIndexOrThrow(Events.TIMESTAMP));
        screenOn = c.getInt(c.getColumnIndexOrThrow(Events.SCREEN_ON)) == 1;
        wifiConnected = c.getInt(c.getColumnIndexOrThrow(Events.WIFI_CONNECTED)) == 1;
        mobileConnected = c.getInt(c.getColumnIndexOrThrow(Events.MOBILE_CONNECTED)) == 1;
        mobileOperator = c.getString(c.getColumnIndexOrThrow(Events.MOBILE_OPERATOR));
        if (mobileOperator != null) {
            mobileOperator = mobileOperator.intern();
        }
        batteryLevel = c.getInt(c.getColumnIndexOrThrow(Events.BATTERY_LEVEL));
        powerOn = c.getInt(c.getColumnIndexOrThrow(Events.POWER_ON)) == 1;
    }

    /**
     * Fill a {@link ContentValues} instance with values from this instance.
     */
    public void write(ContentValues values) {
        values.put(Events.TIMESTAMP, timestamp);
        values.put(Events.SCREEN_ON, screenOn ? 1 : 0);
        values.put(Events.WIFI_CONNECTED, wifiConnected ? 1 : 0);
        values.put(Events.MOBILE_CONNECTED, mobileConnected ? 1 : 0);
        values.put(Events.MOBILE_OPERATOR, mobileOperator);
        values.put(Events.BATTERY_LEVEL, batteryLevel);
        values.put(Events.POWER_ON, powerOn ? 1 : 0);
    }

    @Override
    public String toString() {
        return "Event[timestamp=" + DateFormat.format("dd/MM/yyyy hh:mm:ss", timestamp) + "; screen="
                + screenOn + "; wifi=" + wifiConnected + "; mobile=" + mobileConnected + "; operator="
                + mobileOperator + "; battery=" + batteryLevel + "; powerOn=" + powerOn + "]";
    }
} public enum MobileOperator {
    FREE_MOBILE, ORANGE;

    private static final Set<String> FREE_MOBILE_IDENTIFIERS = new HashSet<String>(2);
    private static final Set<String> ORANGE_IDENTIFIERS = new HashSet<String>(3);

    static {
        // MCC+MNC identifier list:
        // http://en.wikipedia.org/wiki/Mobile_Network_Code
        FREE_MOBILE_IDENTIFIERS.add("20815");
        FREE_MOBILE_IDENTIFIERS.add("20816");
        ORANGE_IDENTIFIERS.add("20800");
        ORANGE_IDENTIFIERS.add("20801");
        ORANGE_IDENTIFIERS.add("20802");
    }

    /**
     * Get a {@link MobileOperator} instance from a MCC+MNC identifier.
     */
    public static MobileOperator fromString(String mccMnc) {
        if (mccMnc == null) {
            return null;
        }
        if (ORANGE_IDENTIFIERS.contains(mccMnc)) {
            return ORANGE;
        }
        if (FREE_MOBILE_IDENTIFIERS.contains(mccMnc)) {
            return FREE_MOBILE;
        }
        if (DEBUG) {
            Log.v(TAG, "Unknown MCC+MNC: " + mccMnc);
        }
        return null;
    }

    public static MobileOperator fromString(CharArrayBuffer mccMnc) {
        if (mccMnc == null || mccMnc.sizeCopied != 5 || mccMnc.data[0] != '2' || mccMnc.data[1] != '0'
                || mccMnc.data[2] != '8') {
            return null;
        }
        if (mccMnc.data[3] == '0' && mccMnc.data[4] == '0' || mccMnc.data[3] == '0' && mccMnc.data[4] == '1'
                || mccMnc.data[3] == '0' && mccMnc.data[4] == '2') {
            return ORANGE;
        }
        if (mccMnc.data[3] == '1' && mccMnc.data[4] == '4' || mccMnc.data[3] == '1' && mccMnc.data[4] == '5') {
            return FREE_MOBILE;
        }
        if (DEBUG) {
            Log.v(TAG, "Unknown MCC+MNC: " + new String(mccMnc.data));
        }
        return null;
    }

    public String toName(Context context) {
        if (FREE_MOBILE.equals(this)) {
            return context.getString(R.string.network_free_mobile);
        }
        if (ORANGE.equals(this)) {
            return context.getString(R.string.network_orange);
        }
        return context.getString(R.string.network_unknown);
    }
} public static class Events implements BaseColumns, EventsColumns {
    /**
     * The content:// style URI for this table.
     */
    public static final Uri CONTENT_URI = new Uri.Builder()
            .scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
            .appendPath("events").build();
    /**
     * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
     * entry.
     */
    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/event";
    /**
     * The MIME type of {@link #CONTENT_TYPE} providing a directory of
     * entries.
     */
    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/event";
} public static class Statistics {
    public Event[] events = new Event[0];
    public long orangeTime;
    public long freeMobileTime;
    public int orangeUsePercent;
    public int freeMobileUsePercent;
    public MobileOperator mobileOperator;
    public String mobileOperatorCode;
    public long connectionTime;
    public long screenOnTime;
    public long wifiOnTime;
    public int battery;

    @Override
    public String toString() {
        return "Statistics[events=" + events.length + "; orange=" + orangeUsePercent + "%; free="
                + freeMobileUsePercent + "%]";
    }
} public final class DateUtils {
    private DateUtils() {
    }

    /**
     * Format a duration in milliseconds.
     */
    public static CharSequence formatDuration(long duration, Context context, CharSequence defaultValue) {
        if (duration <= 0) {
            return defaultValue;
        }
        final long ds = duration / 1000;
        final StringBuilder buf = new StringBuilder(32);
        if (ds < 60) {
            buf.append(ds).append(context.getString(R.string.seconds));
        } else if (ds < 3600) {
            final long m = ds / 60;
            buf.append(m).append(context.getString(R.string.minutes));
        } else if (ds < 86400) {
            final long h = ds / 3600;
            buf.append(h).append(context.getString(R.string.hours));

            final long m = (ds - h * 3600) / 60;
            if (m != 0) {
                if (m < 10) {
                    buf.append("0");
                }
                buf.append(m);
            }
        } else {
            final long d = ds / 86400;
            buf.append(d).append(context.getString(R.string.days));

            final long h = (ds - d * 86400) / 3600;
            if (h != 0) {
                buf.append(" ").append(h).append(context.getString(R.string.hours));
            }

            final long m = (ds - d * 86400 - h * 3600) / 60;
            if (m != 0) {
                if (h == 0) {
                    buf.append(" ");
                } else if (m < 10) {
                    buf.append("0");
                }
                buf.append(m);
                if (h == 0) {
                    buf.append(context.getString(R.string.minutes));
                }
            }
        }

        return buf;
    }

    /**
     * Format a date.
     */
    public static CharSequence formatDate(long d) {
        return DateFormat.format("dd/MM/yyyy", d);
    }
}
import static org.pixmob.freemobile.netstat.BuildConfig.DEBUG;
import static org.pixmob.freemobile.netstat.Constants.INTERVAL_ONE_MONTH;
import static org.pixmob.freemobile.netstat.Constants.INTERVAL_ONE_WEEK;
import static org.pixmob.freemobile.netstat.Constants.INTERVAL_TODAY;
import static org.pixmob.freemobile.netstat.Constants.SP_KEY_TIME_INTERVAL;
import static org.pixmob.freemobile.netstat.Constants.SP_NAME;
import static org.pixmob.freemobile.netstat.Constants.TAG;
import java.util.Calendar;
import java.util.Date;
import org.pixmob.freemobile.netstat.Event;
import org.pixmob.freemobile.netstat.MobileOperator;
import org.pixmob.freemobile.netstat.R;
import org.pixmob.freemobile.netstat.content.NetstatContract.Events;
import org.pixmob.freemobile.netstat.ui.StatisticsFragment.Statistics;
import org.pixmob.freemobile.netstat.util.DateUtils;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.telephony.TelephonyManager;
import android.text.format.Time;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
    @Override
    public void onResume() {
        super.onResume();
        // Monitor database updates if the fragment is displayed.
        final ContentResolver cr = getActivity().getContentResolver();
        cr.registerContentObserver(Events.CONTENT_URI, true, contentMonitor);
    }

    @Override
    public void onPause() {
        super.onPause();
        // Stop monitoring database updates.
        getActivity().getContentResolver().unregisterContentObserver(contentMonitor);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.statistics_fragment, container, false);
    }

    public void refresh() {
        if (isDetached()) {
            return;
        }
        if (getLoaderManager().hasRunningLoaders()) {
            if (DEBUG) {
                Log.d(TAG, "Skip statistics refresh: already running");
            }
            return;
        }
        if (DEBUG) {
            Log.d(TAG, "Refresh statistics");
        }
        getLoaderManager().restartLoader(0, null, this);
    }

    @Override
    public Loader<Statistics> onCreateLoader(int id, Bundle args) {
        progressBar.setVisibility(View.VISIBLE);

        return new StatisticsLoader(getActivity());
    }

    @Override
    public void onLoaderReset(Loader<Statistics> loader) {
    }

    @Override
    public void onLoadFinished(Loader<Statistics> loader, Statistics s) {
        Log.i(TAG, "Statistics loaded: " + s);

        onOrangeNetwork.setText(s.orangeUsePercent + "%");
        onFreeMobileNetwork.setText(s.freeMobileUsePercent + "%");
        mobileNetworkChart.setData(s.orangeUsePercent, s.freeMobileUsePercent);

        final Activity a = getActivity();
        statMobileNetwork.setText(s.mobileOperator == null ? STAT_NO_VALUE : s.mobileOperator.toName(a));
        statMobileCode.setText(s.mobileOperatorCode == null ? STAT_NO_VALUE : s.mobileOperatorCode);
        setDurationText(statScreenOn, s.screenOnTime);
        setDurationText(statWifiOn, s.wifiOnTime);
        setDurationText(statOnOrange, s.orangeTime);
        setDurationText(statOnFreeMobile, s.freeMobileTime);

        statBattery.setText(s.battery == 0 ? STAT_NO_VALUE : String.valueOf(s.battery) + "%");

        batteryChart.setData(s.events);

        progressBar.setVisibility(View.INVISIBLE);
        statisticsGroup.setVisibility(View.VISIBLE);
        statisticsGroup.invalidate();
        batteryChart.invalidate();
    }

    private void setDurationText(TextView tv, long duration) {
        if (duration < 1) {
            tv.setText(STAT_NO_VALUE);
        } else {
            tv.setText(formatDuration(duration));
        }
    }

    /**
     * Return a formatted string for a duration value.
     */
    private CharSequence formatDuration(long duration) {
        return DateUtils.formatDuration(duration, getActivity(), STAT_NO_VALUE);
    }

    /**
     * {@link Loader} implementation for loading events from the database, and
     * computing statistics.
     * @author Pixmob
     */
    private static class StatisticsLoader extends AsyncTaskLoader<Statistics> {
        public StatisticsLoader(final Context context) {
            super(context);

            if (DEBUG) {
                Log.d(TAG, "New StatisticsLoader");
            }
        }

        @Override
        protected void onStartLoading() {
            super.onStartLoading();
            forceLoad();

            if (DEBUG) {
                Log.d(TAG, "StatisticsLoader.onStartLoading()");
            }
        }

        @Override
        public Statistics loadInBackground() {
            if (DEBUG) {
                Log.d(TAG, "StatisticsLoader.loadInBackground()");
            }

            final long now = System.currentTimeMillis();

            final SharedPreferences prefs = getContext().getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);