net.named_data.nfd.MainFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.named_data.nfd.MainFragment.java

Source

/* -*- Mode:jde; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2015 Regents of the University of California
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon) Android.
 * See AUTHORS.md for complete list of NFD Android authors and contributors.
 *
 * NFD Android 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.
 *
 * NFD Android 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
 * NFD Android, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.named_data.nfd;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;

import com.intel.jndn.management.types.ForwarderStatus;

import net.named_data.nfd.service.NfdService;
import net.named_data.nfd.utils.G;
import net.named_data.nfd.utils.NfdcHelper;

import org.joda.time.Period;
import org.joda.time.format.PeriodFormat;

public class MainFragment extends Fragment {

    public static MainFragment newInstance() {
        // Create fragment arguments here (if necessary)
        return new MainFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        m_handler = new Handler();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        @SuppressLint("InflateParams")
        View v = inflater.inflate(R.layout.fragment_main, null);

        m_nfdStartStopSwitch = (Switch) v.findViewById(R.id.nfd_start_stop_switch);
        m_nfdStartStopSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isOn) {
                m_sharedPreferences.edit().putBoolean(PREF_NFD_SERVICE_STATUS, isOn).apply();

                if (isOn) {
                    startNfdService();
                } else {
                    stopNfdService();
                }
            }
        });

        m_nfdStatusView = (ViewGroup) v.findViewById(R.id.status_view);
        m_nfdStatusView.setVisibility(View.GONE);
        m_versionView = (TextView) v.findViewById(R.id.version);
        m_uptimeView = (TextView) v.findViewById(R.id.uptime);
        m_nameTreeEntriesView = (TextView) v.findViewById(R.id.name_tree_entries);
        m_fibEntriesView = (TextView) v.findViewById(R.id.fib_entries);
        m_pitEntriesView = (TextView) v.findViewById(R.id.pit_entries);
        m_measurementEntriesView = (TextView) v.findViewById(R.id.measurement_entries);
        m_csEntriesView = (TextView) v.findViewById(R.id.cs_entries);
        m_inInterestsView = (TextView) v.findViewById(R.id.in_interests);
        m_outInterestsView = (TextView) v.findViewById(R.id.out_interests);
        m_inDataView = (TextView) v.findViewById(R.id.in_data);
        m_outDataView = (TextView) v.findViewById(R.id.out_data);
        m_inNacksView = (TextView) v.findViewById(R.id.in_nacks);
        m_outNacksView = (TextView) v.findViewById(R.id.out_nacks);

        return v;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        m_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
    }

    @Override
    public void onResume() {
        super.onResume();

        bindNfdService();
    }

    @Override
    public void onPause() {
        super.onPause();

        unbindNfdService();
        m_handler.removeCallbacks(m_statusUpdateRunnable);
        m_handler.removeCallbacks(m_retryConnectionToNfdService);
    }

    /**
     * Method that binds the current activity to the NfdService.
     */
    private void bindNfdService() {
        if (!m_isNfdServiceConnected) {
            // Bind to Service
            getActivity().bindService(new Intent(getActivity(), NfdService.class), m_ServiceConnection,
                    Context.BIND_AUTO_CREATE);
            G.Log("MainFragment::bindNfdService()");
        }
    }

    /**
     * Method that unbinds the current activity from the NfdService.
     */
    private void unbindNfdService() {
        if (m_isNfdServiceConnected) {
            // Unbind from Service
            getActivity().unbindService(m_ServiceConnection);
            m_isNfdServiceConnected = false;

            G.Log("MainFragment::unbindNfdService()");
        }
    }

    private void startNfdService() {
        assert m_isNfdServiceConnected;

        m_nfdStartStopSwitch.setText(R.string.starting_nfd);
        sendNfdServiceMessage(NfdService.START_NFD_SERVICE);
    }

    private void stopNfdService() {
        assert m_isNfdServiceConnected;

        m_nfdStartStopSwitch.setText(R.string.stopping_nfd);
        sendNfdServiceMessage(NfdService.STOP_NFD_SERVICE);

        // disable status block
        m_nfdStatusView.setVisibility(View.GONE);
        m_handler.removeCallbacks(m_statusUpdateRunnable);
    }

    /**
     * Convenience method to send a message to the NfdService
     * through a Messenger.
     *
     * @param message Message from a set of predefined NfdService messages.
     */
    private void sendNfdServiceMessage(int message) {
        if (m_nfdServiceMessenger == null) {
            G.Log("NfdService not yet connected");
            return;
        }
        try {
            Message msg = Message.obtain(null, message);
            msg.replyTo = m_clientMessenger;
            m_nfdServiceMessenger.send(msg);
        } catch (RemoteException e) {
            // If Service crashes, nothing to do here
            G.Log("Service Disconnected: " + e);
        }
    }

    private void setNfdServiceRunning() {
        m_nfdStartStopSwitch.setEnabled(true);
        m_nfdStartStopSwitch.setText(R.string.nfd_started);
        m_nfdStartStopSwitch.setChecked(true);
    }

    private void setNfdServiceStopped() {
        m_nfdStartStopSwitch.setEnabled(true);
        m_nfdStartStopSwitch.setText(R.string.nfd_stopped);
        m_nfdStartStopSwitch.setChecked(false);

    }

    private void setNfdServiceDisconnected() {
        m_nfdStartStopSwitch.setEnabled(false);
        m_nfdStartStopSwitch.setText(R.string.reconnect_to_nfd);
        m_nfdStartStopSwitch.setChecked(false);
    }

    /**
     * Client Message Handler.
     *
     * This handler is used to handle messages that are being sent back
     * from the NfdService to the current application.
     */
    private class ClientHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case NfdService.NFD_SERVICE_RUNNING:
                setNfdServiceRunning();
                G.Log("ClientHandler: NFD is Running.");

                m_handler.postDelayed(m_statusUpdateRunnable, 500);
                break;

            case NfdService.NFD_SERVICE_STOPPED:
                setNfdServiceStopped();
                G.Log("ClientHandler: NFD is Stopped.");
                break;

            default:
                super.handleMessage(msg);
                break;
            }
        }
    }

    /**
     * Client ServiceConnection to NfdService.
     */
    private final ServiceConnection m_ServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // Establish Messenger to the Service
            m_nfdServiceMessenger = new Messenger(service);
            m_isNfdServiceConnected = true; // onServiceConnected runs on the main thread

            // Check if NFD Service is running
            try {
                boolean shouldServiceBeOn = m_sharedPreferences.getBoolean(PREF_NFD_SERVICE_STATUS, true);

                Message msg = Message.obtain(null,
                        shouldServiceBeOn ? NfdService.START_NFD_SERVICE : NfdService.STOP_NFD_SERVICE);
                msg.replyTo = m_clientMessenger;
                m_nfdServiceMessenger.send(msg);
            } catch (RemoteException e) {
                // If Service crashes, nothing to do here
                G.Log("onServiceConnected(): " + e);
            }

            G.Log("m_ServiceConnection::onServiceConnected()");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            // In event of unexpected disconnection with the Service; Not expecting to get here.
            G.Log("m_ServiceConnection::onServiceDisconnected()");

            // Update UI
            setNfdServiceDisconnected();

            m_isNfdServiceConnected = false; // onServiceDisconnected runs on the main thread
            m_handler.postDelayed(m_retryConnectionToNfdService, 1000);
        }
    };

    /**
     * Attempt to reconnect to the NfdService.
     *
     * This method attempts to reconnect the application to the NfdService
     * when the NfdService has been killed (either by the user or by the OS).
     */
    private Runnable m_retryConnectionToNfdService = new Runnable() {
        @Override
        public void run() {
            G.Log("Retrying connection to NFD Service ...");
            bindNfdService();
        }
    };

    private class StatusUpdateTask extends AsyncTask<Void, Void, ForwarderStatus> {
        /**
         * @param voids
         * @return ForwarderStatus if operation succeeded, null if operation failed
         */
        @Override
        protected ForwarderStatus doInBackground(Void... voids) {
            try {
                NfdcHelper nfdcHelper = new NfdcHelper();
                ForwarderStatus fs = nfdcHelper.generalStatus();
                nfdcHelper.shutdown();
                return fs;
            } catch (Exception e) {
                G.Log("Error communicating with NFD (" + e.getMessage() + ")");
                return null;
            }
        }

        @Override
        protected void onPostExecute(ForwarderStatus fs) {
            if (fs == null) {
                // when failed, try after 0.5 seconds
                m_handler.postDelayed(m_statusUpdateRunnable, 500);
            } else {
                m_versionView.setText(fs.getNfdVersion());
                m_uptimeView.setText(PeriodFormat.getDefault()
                        .print(new Period(fs.getCurrentTimestamp() - fs.getStartTimestamp())));
                m_nameTreeEntriesView.setText(String.valueOf(fs.getNNameTreeEntries()));
                m_fibEntriesView.setText(String.valueOf(fs.getNFibEntries()));
                m_pitEntriesView.setText(String.valueOf(fs.getNPitEntries()));
                m_measurementEntriesView.setText(String.valueOf(fs.getNMeasurementsEntries()));
                m_csEntriesView.setText(String.valueOf(fs.getNCsEntries()));

                m_inInterestsView.setText(String.valueOf(fs.getNInInterests()));
                m_outInterestsView.setText(String.valueOf(fs.getNOutInterests()));

                m_inDataView.setText(String.valueOf(fs.getNInDatas()));
                m_outDataView.setText(String.valueOf(fs.getNOutDatas()));

                m_inNacksView.setText(String.valueOf(fs.getNInNacks()));
                m_outNacksView.setText(String.valueOf(fs.getNOutNacks()));

                m_nfdStatusView.setVisibility(View.VISIBLE);

                // refresh after 5 seconds
                m_handler.postDelayed(m_statusUpdateRunnable, 5000);
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////////

    /** Button that starts and stops the NFD */
    private Switch m_nfdStartStopSwitch;

    /** Flag that marks that application is connected to the NfdService */
    private boolean m_isNfdServiceConnected = false;

    /** Client Message Handler */
    private final Messenger m_clientMessenger = new Messenger(new ClientHandler());

    /** Messenger connection to NfdService */
    private Messenger m_nfdServiceMessenger = null;

    /** ListView holding NFD status information */
    private ViewGroup m_nfdStatusView;

    private TextView m_versionView;
    private TextView m_uptimeView;
    private TextView m_nameTreeEntriesView;
    private TextView m_fibEntriesView;
    private TextView m_pitEntriesView;
    private TextView m_measurementEntriesView;
    private TextView m_csEntriesView;
    private TextView m_inInterestsView;
    private TextView m_outInterestsView;
    private TextView m_inDataView;
    private TextView m_outDataView;
    private TextView m_inNacksView;
    private TextView m_outNacksView;

    private Handler m_handler;
    private Runnable m_statusUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            new StatusUpdateTask().execute();
        }
    };

    private SharedPreferences m_sharedPreferences;

    private static final String PREF_NFD_SERVICE_STATUS = "NFD_SERVICE_STATUS";
}