package com.kedzie.vbox.machine.group; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Future; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Parcel; 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.view.ViewGroup.LayoutParams; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import com.actionbarsherlock.app.SherlockFragment; import com.kedzie.vbox.R; import com.kedzie.vbox.api.IMachine; import com.kedzie.vbox.api.Screenshot; import com.kedzie.vbox.api.jaxb.CPUPropertyType; import com.kedzie.vbox.api.jaxb.DeviceType; import com.kedzie.vbox.api.jaxb.HWVirtExPropertyType; import com.kedzie.vbox.api.jaxb.MachineState; import com.kedzie.vbox.api.jaxb.VBoxEventType; import com.kedzie.vbox.app.CollapsiblePanelView; import com.kedzie.vbox.app.Utils; import com.kedzie.vbox.task.ActionBarTask; import com.kedzie.vbox.task.MachineCallable; /** * * @author Marek Kędzierski * @apiviz.stereotype fragment */ public class GroupInfoFragment extends SherlockFragment { private static final String TAG = "GroupInfoFragment"; static final ClassLoader LOADER = GroupInfoFragment.class.getClassLoader(); public static class MachineInfo implements Parcelable { public static final Parcelable.Creator<MachineInfo> CREATOR = new Parcelable.Creator<MachineInfo>() { @Override public MachineInfo createFromParcel(Parcel source) { return new MachineInfo((IMachine)source.readParcelable(LOADER),(Screenshot)source.readParcelable(LOADER)); } @Override public MachineInfo[] newArray(int size) { return new MachineInfo[size]; } }; public IMachine machine; public Screenshot screenshot; public MachineInfo(IMachine m, Screenshot screenshot) { this.machine=m; this.screenshot=screenshot; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(machine, flags); dest.writeParcelable(screenshot, flags); } @Override public int describeContents() { return 0; } } class LoadInfoTask extends ActionBarTask<VMGroup, ArrayList<MachineInfo>> { public LoadInfoTask() { super(getSherlockActivity(), null); } @Override protected ArrayList<MachineInfo> work(VMGroup... g) throws Exception { LinkedList<Future<MachineInfo>> futures = new LinkedList<Future<MachineInfo>>(); for(TreeNode child : g[0].getChildren()) { if(child instanceof IMachine) { // IMachine m = (IMachine)child; futures.add(getExecutor().submit(new MachineCallable<MachineInfo>((IMachine)child) { @Override public MachineInfo call() throws Exception { Utils.cacheProperties(m); m.getGroups(); m.getMemorySize(); m.getCPUCount(); m.getHWVirtExProperty(HWVirtExPropertyType.NESTED_PAGING); m.getHWVirtExProperty(HWVirtExPropertyType.ENABLED); m.getCPUProperty(CPUPropertyType.PAE); for(int i=1;i<=99; i++) { if(m.getBootOrder(i).equals(DeviceType.NULL)) break; } int size = getResources().getDimensionPixelSize(R.dimen.screenshot_size); MachineInfo mi = new MachineInfo(m, null); if(m.getState().equals(MachineState.SAVED)) { mi.screenshot = _vmgr.readSavedScreenshot(m, 0); mi.screenshot.scaleBitmap(size, size); }else if(m.getState().equals(MachineState.RUNNING)) { try { mi.screenshot = _vmgr.takeScreenshot(m, size, size); } catch(IOException e) { Log.e(TAG, "Exception taking screenshot", e); } } return mi; } })); // info.add(mi); } } ArrayList<MachineInfo> info = new ArrayList<MachineInfo>(g[0].getChildren().size()); for(Future<MachineInfo> future : futures) info.add(future.get()); return info; } @Override protected void onSuccess(ArrayList<MachineInfo> result) { _info = result; populateViews(result); } } private VMGroup _group; private int _maxBootPosition; private ArrayList<MachineInfo> _info; private LinearLayout _view; 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())) { new LoadInfoTask().execute(_group); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(savedInstanceState!=null) { _group = savedInstanceState.getParcelable(VMGroup.BUNDLE); _maxBootPosition = savedInstanceState.getInt("maxBootPosition"); _info = savedInstanceState.getParcelableArrayList("info"); } else { _group = getArguments().getParcelable(VMGroup.BUNDLE); } } @Override public void onSaveInstanceState(Bundle outState) { outState.putParcelable(VMGroup.BUNDLE, _group); outState.putParcelableArrayList("info", _info); outState.putInt("maxBootPosition", _maxBootPosition); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { _view = new LinearLayout(getActivity()); _view.setOrientation(LinearLayout.VERTICAL); ScrollView scrollView = new ScrollView(getActivity()); scrollView.addView(_view); return scrollView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); lbm = LocalBroadcastManager.getInstance(getActivity().getApplicationContext()); if(_info!=null) populateViews(_info); else new LoadInfoTask().execute(_group); } @Override public void onStart() { super.onStart(); lbm.registerReceiver(_receiver, Utils.createIntentFilter(VBoxEventType.ON_MACHINE_STATE_CHANGED.name())); } @Override public void onStop() { lbm.unregisterReceiver(_receiver); super.onStop(); } private void populateViews(List<MachineInfo> m) { LayoutInflater inflater = LayoutInflater.from(getActivity()); for(MachineInfo node : m) { View view = inflater.inflate(R.layout.group_info, _view, false); Utils.setTextView(view, R.id.name, node.machine.getName()); Utils.setTextView(view, R.id.ostype, node.machine.getOSTypeId()); if(!Utils.isEmpty(node.machine.getGroups())) Utils.setTextView(view, R.id.groups, node.machine.getGroups().get(0)); Utils.setTextView(view, R.id.baseMemory, node.machine.getMemorySize()+""); Utils.setTextView(view, R.id.processors, node.machine.getCPUCount()+""); String acceleration = ""; if(node.machine.getHWVirtExProperty(HWVirtExPropertyType.ENABLED)) acceleration="VT-x/AMD-V"; if(node.machine.getHWVirtExProperty(HWVirtExPropertyType.NESTED_PAGING)) acceleration+=(acceleration.equals("") ? "" : ", ") + "Nested Paging"; if(node.machine.getCPUProperty(CPUPropertyType.PAE)) acceleration+=(acceleration.equals("") ? "" : ", ") + "PAE/NX"; Utils.setTextView(view, R.id.acceleration, acceleration); StringBuffer bootOrder = new StringBuffer(); for(int i=1; i<=99; i++) { DeviceType b = node.machine.getBootOrder(i); if(b.equals(DeviceType.NULL)) break; Utils.appendWithComma(bootOrder, b.toString()); } Utils.setTextView(view, R.id.bootOrder, bootOrder.toString()); CollapsiblePanelView previewPanel = (CollapsiblePanelView)view.findViewById(R.id.previewPanel); if(node.screenshot!=null) { ImageView preview = (ImageView)view.findViewById(R.id.preview); preview.setAdjustViewBounds(true); preview.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); preview.setImageBitmap(node.screenshot.getBitmap()); previewPanel.expand(); } else { previewPanel.collapse(); } _view.addView(view); } } @Override public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) { switch(item.getItemId()) { case R.id.option_menu_refresh: new LoadInfoTask().execute(_group); return true; } return false; } }