package com.kedzie.vbox.machine; import java.util.Map; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.view.MenuItem; import com.kedzie.vbox.R; import com.kedzie.vbox.VBoxApplication; import com.kedzie.vbox.VMAction; import com.kedzie.vbox.api.IConsole; import com.kedzie.vbox.api.IDisplay; import com.kedzie.vbox.api.IEvent; import com.kedzie.vbox.api.IMachine; import com.kedzie.vbox.api.IProgress; import com.kedzie.vbox.api.ISessionStateChangedEvent; import com.kedzie.vbox.api.jaxb.SessionState; import com.kedzie.vbox.api.jaxb.VBoxEventType; import com.kedzie.vbox.app.BundleBuilder; import com.kedzie.vbox.app.Utils; import com.kedzie.vbox.event.EventIntentService; import com.kedzie.vbox.machine.settings.VMSettingsActivity; import com.kedzie.vbox.metrics.MetricActivity; import com.kedzie.vbox.soap.VBoxSvc; import com.kedzie.vbox.task.ActionBarTask; import com.kedzie.vbox.task.LaunchVMProcessTask; import com.kedzie.vbox.task.MachineTask; /** * * @author Marek Kędzierski * @apiviz.stereotype fragment */ public class ActionsFragment extends SherlockFragment implements OnItemClickListener { protected static final String TAG = ActionsFragment.class.getSimpleName(); private MachineView _headerView; private ListView _listView; /** VirtualBox API */ private VBoxSvc _vmgr; /** The Virtual Machine */ private IMachine _machine; private LocalBroadcastManager lbm; /** Event-handling local broadcasts */ private BroadcastReceiver _receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "Recieved Broadcast: " + intent.getAction()); if(intent.getAction().equals(VBoxEventType.ON_MACHINE_STATE_CHANGED.name())) { IMachine m = BundleBuilder.getProxy(intent.getExtras(), IMachine.BUNDLE, IMachine.class); new UpdateMachineViewTask(_vmgr).execute(m); } else if (intent.getAction().equals(VBoxEventType.ON_SESSION_STATE_CHANGED.name())) { new HandleSessionChangedEvent(_vmgr).execute(intent.getExtras()); } } }; /** * Load Machine properties from web server */ class UpdateMachineViewTask extends ActionBarTask<IMachine, IMachine> { public UpdateMachineViewTask(VBoxSvc vmgr) { super(getSherlockActivity(), vmgr); } @Override protected IMachine work(IMachine... m) throws Exception { Utils.cacheProperties(m[0]); m[0].getMemorySize(); m[0].getSessionState(); return m[0]; } @Override protected void onSuccess(IMachine result) { _machine=result; _headerView.update(result); if(getActivity()!=null) _listView.setAdapter(new MachineActionAdapter(VMAction.getVMActions(result.getState()))); } } /** * Handle SessionStateChanged event */ class HandleSessionChangedEvent extends ActionBarTask<Bundle, SessionState> { public HandleSessionChangedEvent(VBoxSvc vmgr) { super(getSherlockActivity(), vmgr); } @Override protected SessionState work(Bundle... params) throws Exception { ISessionStateChangedEvent event = (ISessionStateChangedEvent)BundleBuilder.getProxy(params[0], EventIntentService.BUNDLE_EVENT, IEvent.class); return event.getState(); } @Override protected void onSuccess(SessionState result) { } } /** * List Adapter for Virtual Machine Actions */ class MachineActionAdapter extends ArrayAdapter<VMAction> { private final LayoutInflater _layoutInflater; public MachineActionAdapter(VMAction []actions) { super(getActivity(), 0, actions); _layoutInflater = LayoutInflater.from(getActivity()); } public View getView(int position, View view, ViewGroup parent) { if (view == null) view = _layoutInflater.inflate(R.layout.machine_action_item, parent, false); ((TextView)view.findViewById(R.id.action_item_text)).setText(getItem(position).toString()); ((ImageView)view.findViewById(R.id.action_item_icon)).setImageResource( getApp().getDrawable(getItem(position))); return view; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); _vmgr = getArguments().getParcelable(VBoxSvc.BUNDLE); _machine = BundleBuilder.getProxy(savedInstanceState!=null ? savedInstanceState : getArguments(), IMachine.BUNDLE, IMachine.class); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { _headerView = new MachineView(getActivity()); _listView = new ListView(getActivity()); _listView.setClipChildren(false); _listView.addHeaderView(_headerView); _listView.setOnItemClickListener(this); return _listView; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); lbm = LocalBroadcastManager.getInstance(getActivity().getApplicationContext()); new UpdateMachineViewTask(_vmgr).execute(_machine); } @Override public void onStart() { super.onStart(); lbm.registerReceiver(_receiver, Utils.createIntentFilter( VBoxEventType.ON_MACHINE_STATE_CHANGED.name(), VBoxEventType.ON_SESSION_STATE_CHANGED.name())); } @Override public void onStop() { lbm.unregisterReceiver(_receiver); super.onStop(); } @Override public void onSaveInstanceState(Bundle outState) { BundleBuilder.putProxy(outState, IMachine.BUNDLE, _machine); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.option_menu_refresh: new UpdateMachineViewTask(_vmgr).execute(_machine); return true; } return false; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { VMAction action = (VMAction)_listView.getAdapter().getItem(position); if(action==null) return; if(action.equals(VMAction.START)) new LaunchVMProcessTask(getSherlockActivity(), _vmgr).execute(_machine); else if(action.equals(VMAction.POWER_OFF)) new MachineTask<IMachine, Void>(getSherlockActivity(), _vmgr, R.string.progress_powering_off, false, _machine) { protected IProgress workWithProgress(IMachine m, IConsole console, IMachine...i) throws Exception { return console.powerDown(); } }.execute(_machine); else if(action.equals(VMAction.RESET)) new MachineTask<IMachine, Void>(getSherlockActivity(), _vmgr, R.string.progress_restarting, true, _machine) { protected Void work(IMachine m, IConsole console, IMachine...i) throws Exception { console.reset(); return null; } }.execute(_machine); else if(action.equals(VMAction.PAUSE)) new MachineTask<IMachine, Void>(getSherlockActivity(), _vmgr, R.string.progress_pausing, true, _machine) { protected Void work(IMachine m, IConsole console, IMachine...i) throws Exception { console.pause(); return null; } }.execute(_machine); else if(action.equals(VMAction.RESUME)) new MachineTask<IMachine, Void>(getSherlockActivity(), _vmgr, R.string.progress_resuming, true, _machine) { protected Void work(IMachine m, IConsole console, IMachine...i) throws Exception { console.resume(); return null; } }.execute(_machine); else if(action.equals(VMAction.POWER_BUTTON)) new MachineTask<IMachine, Void>( getSherlockActivity(), _vmgr, R.string.progress_acpi_down, true, _machine) { protected Void work(IMachine m, IConsole console,IMachine...i) throws Exception { console.powerButton(); return null; } }.execute(_machine); else if(action.equals(VMAction.SAVE_STATE)) new MachineTask<IMachine, Void>( getSherlockActivity(), _vmgr, R.string.progress_saving_state, false, _machine) { protected IProgress workWithProgress(IMachine m, IConsole console, IMachine...i) throws Exception { return console.saveState(); } }.execute(_machine); else if(action.equals(VMAction.DISCARD_STATE)) new MachineTask<IMachine, Void>( getSherlockActivity(), _vmgr, R.string.progress_discarding_state, true, _machine) { protected Void work(IMachine m, IConsole console, IMachine...i) throws Exception { console.discardSavedState(true); return null; } }.execute(_machine); else if(action.equals(VMAction.TAKE_SNAPSHOT)) { Utils.showDialog(getSherlockActivity().getSupportFragmentManager(), "snapshotDialog", TakeSnapshotFragment.getInstance(_vmgr, _machine, null) ); } else if(action.equals(VMAction.VIEW_METRICS)) { startActivity(new Intent(getActivity(), MetricActivity.class).putExtra(VBoxSvc.BUNDLE, (Parcelable)_vmgr) .putExtra(MetricActivity.INTENT_TITLE, _machine.getName() + " Metrics") .putExtra(MetricActivity.INTENT_OBJECT, _machine.getIdRef() ) .putExtra(MetricActivity.INTENT_RAM_AVAILABLE, _machine.getMemorySize() ) .putExtra(MetricActivity.INTENT_CPU_METRICS , new String[] { "CPU/Load/User", "CPU/Load/Kernel" } ) .putExtra(MetricActivity.INTENT_RAM_METRICS , new String[] { "RAM/Usage/Used" } )); } else if(action.equals(VMAction.TAKE_SCREENSHOT)) { new MachineTask<Void, byte []>(getSherlockActivity(), _vmgr, R.string.progress_taking_snapshot, true, _machine) { protected byte[] work(IMachine m, IConsole console, Void...i) throws Exception { IDisplay display = console.getDisplay(); Map<String, String> res = display.getScreenResolution(0); return display.takeScreenShotPNGToArray(0, Integer.valueOf(res.get("width")), Integer.valueOf(res.get("height"))); } @Override protected void onSuccess(byte[] result) { super.onSuccess(result); Utils.showDialog(getSherlockActivity().getSupportFragmentManager(), "screenshotDialog", ScreenshotDialogFragment.getInstance(result) ); } }.execute(); } else if(action.equals(VMAction.EDIT_SETTINGS)) { if(getApp().isPremiumVersion()) { if(!_machine.getSessionState().equals(SessionState.UNLOCKED)) { new AlertDialog.Builder(getActivity()) .setTitle("Cannot edit machine") .setIcon(android.R.drawable.ic_dialog_alert) .setMessage("Session state is " + _machine.getSessionState()) .show(); } else Utils.startActivity(getActivity(), new Intent(getActivity(), VMSettingsActivity.class).putExtras(getArguments())); } else getApp().showPremiumOffer(getActivity()); } } public VBoxApplication getApp() { return (VBoxApplication)getActivity().getApplication(); } }