Skip to content

Commit

Permalink
feat: add decoder options
Browse files Browse the repository at this point in the history
  • Loading branch information
cinit committed Dec 19, 2021
1 parent 2600c31 commit fc09005
Show file tree
Hide file tree
Showing 14 changed files with 445 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import cc.ioctl.nfcdevicehost.R;
import cc.ioctl.nfcdevicehost.decoder.NciPacketDecoder;
import cc.ioctl.nfcdevicehost.decoder.NxpHalV2EventTranslator;
import cc.ioctl.nfcdevicehost.ipc.daemon.INciHostDaemon;
import cc.ioctl.nfcdevicehost.util.ByteUtils;

public abstract class BaseHalDumpFragment extends Fragment {
Expand All @@ -37,8 +43,67 @@ public NciDumpViewHolder(cc.ioctl.nfcdevicehost.databinding.ItemMainNciDumpBindi
}
}

protected void updateListViewItem(@NonNull NciDumpViewHolder holder,
@NonNull NxpHalV2EventTranslator.TransactionEvent event) {
protected void updateListViewItemForAuxIoEvent(@NonNull NciDumpViewHolder holder,
@NonNull INciHostDaemon.IoEventPacket event) {
long timestamp = event.timestamp;
String seqTime;
Date now = new Date();
Date seqTimeDate = new Date(timestamp);
if (now.getYear() == seqTimeDate.getYear() && now.getMonth() == seqTimeDate.getMonth()
&& now.getDate() == seqTimeDate.getDate()) {
// the same day, HH:mm:ss.SSS
seqTime = String.format(Locale.ROOT, "#%d ", event.sequence)
+ String.format(Locale.ROOT, "%1$tH:%1$tM:%1$tS.%1$tL", event.timestamp);
} else {
// not the same day, yyyy-MM-dd HH:mm:ss.SSS
seqTime = String.format(Locale.ROOT, "#%d ", event.sequence)
+ String.format(Locale.ROOT, "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL", event.timestamp);
}
String eventType = event.opType.toString();
StringBuilder sb = new StringBuilder();
switch (event.opType) {
case OPEN: {
String path = event.auxPath;
sb.append(String.format(Locale.ROOT, "open(%s)=%d", path, event.retValue));
break;
}
case CLOSE: {
sb.append(String.format(Locale.ROOT, "close(%d)", event.fd));
break;
}
case READ: {
sb.append(String.format(Locale.ROOT, "read(%d)=%d", event.fd, event.retValue));
sb.append("\ndata(").append(event.directArg2).append(")").append('\n');
sb.append(ByteUtils.bytesToHexString(event.buffer));
break;
}
case WRITE: {
sb.append(String.format(Locale.ROOT, "write(%d)=%d", event.fd, event.retValue));
sb.append("\ndata(").append(event.directArg2).append(")").append('\n');
sb.append(ByteUtils.bytesToHexString(event.buffer));
break;
}
case IOCTL: {
sb.append(String.format(Locale.ROOT, "ioctl(%d, 0x%x, 0x%x)=%d",
event.fd, event.directArg1, event.directArg2, event.retValue));
break;
}
case SELECT: {
sb.append(String.format(Locale.ROOT, "select(%d)=%d", event.fd, event.retValue));
break;
}
default: {
sb.append(String.format(Locale.ROOT, "%s(%d, %d, %d)=%d",
event.opType, event.fd, event.directArg1, event.directArg2, event.retValue));
}
}
holder.binding.textViewItemNciDumpTime.setText(seqTime);
holder.binding.textViewItemNciDumpType.setText(eventType);
holder.binding.textViewItemNciDumpMessage.setText(sb.toString());
}

protected void updateListViewItemForNciPacket(@NonNull NciDumpViewHolder holder,
@NonNull NxpHalV2EventTranslator.TransactionEvent event) {
long timestamp = event.timestamp;
String seqTime;
Date now = new Date();
Expand Down Expand Up @@ -120,6 +185,10 @@ public NciDumpViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewT
parent, false);
return new NciDumpViewHolder(binding, NciDumpViewHolder.ViewType.TRANSACTION);
}

public abstract int getEventSequenceByPosition(int position);

public abstract int findEventPositionBySequence(int sequence);
}

@Override
Expand All @@ -128,8 +197,72 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
}

@UiThread
protected void showDecoderOptionDialog() {
int currentDecoder = getCurrentDecoderIndex();
new AlertDialog.Builder(requireContext())
.setTitle(R.string.ui_hal_dump_decoder_config_title)
.setSingleChoiceItems(R.array.ui_hal_dump_decoder_config_items, currentDecoder, null)
.setCancelable(true)
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
int newDecoder = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
if (newDecoder != -1 && newDecoder != currentDecoder) {
setCurrentDecoderIndex(newDecoder);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
}

protected abstract int getCurrentDecoderIndex();

@UiThread
protected abstract void setCurrentDecoderIndex(int index);

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
requireActivity().getMenuInflater().inflate(R.menu.menu_main_fragment_dump_common, menu);
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_decoder_config: {
showDecoderOptionDialog();
return true;
}
default:
return super.onOptionsItemSelected(item);
}
}

/**
* Find the index of the event list by the given event sequence.
*
* @param packets the event list
* @param sequence the sequence of the event
* @return a non-negative index if found, otherwise the negative value of the index where the event should be inserted.
*/
public static int findItemIndexBySequenceIoEventPacket(List<INciHostDaemon.IoEventPacket> packets, int sequence) {
INciHostDaemon.IoEventPacket dummy = new INciHostDaemon.IoEventPacket();
dummy.sequence = sequence;
return Collections.binarySearch(packets, dummy, (o1, o2) -> {
if (o1.sequence == o2.sequence) {
return 0;
}
return o1.sequence < o2.sequence ? -1 : 1;
});
}

public static int findItemIndexBySequenceTransactionEvent(List<NxpHalV2EventTranslator.TransactionEvent> packets, int sequence) {
NxpHalV2EventTranslator.TransactionEvent dummy = new NxpHalV2EventTranslator.TransactionEvent();
dummy.sequence = sequence;
return Collections.binarySearch(packets, dummy, (o1, o2) -> {
if (o1.sequence == o2.sequence) {
return 0;
}
return o1.sequence < o2.sequence ? -1 : 1;
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,81 @@
public class HalDumpFileViewFragment extends BaseHalDumpFragment {

public static final String EXTRA_CONTENT = HalDumpFileViewFragment.class.getName() + ".EXTRA_CONTENT";
private static final String STATE_CURRENT_DECODER_INDEX = "STATE_CURRENT_DECODER_INDEX";

private String mRawSerializedDumpData = null;
private ArrayList<INciHostDaemon.IoEventPacket> mRawIoEvents = null;
private ArrayList<NxpHalV2EventTranslator.TransactionEvent> mTransactionEvents = null;
private int mCurrentDecoderIndex = 1;

private FragmentMainDumpBinding mBinding;
private final AbsNciDumpAdapter mDumpAdapter = new AbsNciDumpAdapter() {
@Override
public void onBindViewHolder(@NonNull NciDumpViewHolder holder, int position) {
NxpHalV2EventTranslator.TransactionEvent event = mTransactionEvents.get(position);
updateListViewItem(holder, event);
if (mCurrentDecoderIndex == 0) {
// raw aux IO events
INciHostDaemon.IoEventPacket event = mRawIoEvents.get(position);
updateListViewItemForAuxIoEvent(holder, event);
} else if (mCurrentDecoderIndex == 1) {
// decoded NCI packets
NxpHalV2EventTranslator.TransactionEvent event = mTransactionEvents.get(position);
updateListViewItemForNciPacket(holder, event);
} else {
throw new IllegalStateException("Unknown decoder index: " + mCurrentDecoderIndex);
}
}

@Override
public int getItemCount() {
return mTransactionEvents == null ? 0 : mTransactionEvents.size();
if (mCurrentDecoderIndex == 0) {
// raw aux IO events
return mRawIoEvents == null ? 0 : mRawIoEvents.size();
} else if (mCurrentDecoderIndex == 1) {
// decoded NCI packets
return mTransactionEvents == null ? 0 : mTransactionEvents.size();
} else {
throw new IllegalStateException("Unknown decoder index: " + mCurrentDecoderIndex);
}
}

@Override
public int getEventSequenceByPosition(int position) {
if (mCurrentDecoderIndex == 0) {
// raw aux IO events
return mRawIoEvents.get(position).sequence;
} else if (mCurrentDecoderIndex == 1) {
// decoded NCI packets
return (int) mTransactionEvents.get(position).sequence;
} else {
throw new IllegalStateException("Unknown decoder index: " + mCurrentDecoderIndex);
}
}

@Override
public int findEventPositionBySequence(int sequence) {
if (mCurrentDecoderIndex == 0) {
// raw aux IO events
return BaseHalDumpFragment.findItemIndexBySequenceIoEventPacket(mRawIoEvents, sequence);
} else if (mCurrentDecoderIndex == 1) {
// decoded NCI packets
return BaseHalDumpFragment.findItemIndexBySequenceTransactionEvent(mTransactionEvents, sequence);
} else {
throw new IllegalStateException("Unknown decoder index: " + mCurrentDecoderIndex);
}
}
};

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
int idx = savedInstanceState.getInt(STATE_CURRENT_DECODER_INDEX, -1);
if (idx >= 0) {
mCurrentDecoderIndex = idx;
}
}
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
Expand Down Expand Up @@ -95,7 +151,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
NxpHalV2EventTranslator translator = new NxpHalV2EventTranslator();
translator.pushBackRawIoEvents(mRawIoEvents);
mTransactionEvents = translator.getTransactionEvents();
ThreadManager.runOnUiThread(() -> mDumpAdapter.notifyDataSetChanged());
// notify adapter
ThreadManager.runOnUiThread(mDumpAdapter::notifyDataSetChanged);
} catch (RuntimeException e) {
ThreadManager.runOnUiThread(() -> new AlertDialog.Builder(context)
.setTitle(R.string.ui_dialog_error_title)
Expand Down Expand Up @@ -128,8 +185,47 @@ public void onResume() {

}

private void popSelf() {
protected void popSelf() {
requireActivity().onBackPressed();
}

@Override
protected int getCurrentDecoderIndex() {
return mCurrentDecoderIndex;
}

@Override
protected void setCurrentDecoderIndex(int newDecoderIndex) {
// get the current RecyclerView item index
RecyclerView recyclerView = mBinding.recyclerViewMainFragmentDumpList;
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
assert layoutManager != null;
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
View firstVisibleView = firstVisibleItemPosition == RecyclerView.NO_POSITION ? null
: layoutManager.findViewByPosition(firstVisibleItemPosition);
int itemTopOffset = firstVisibleView == null ? 0 : firstVisibleView.getTop();
int currentEventSequence = -1;
if (firstVisibleItemPosition != RecyclerView.NO_POSITION) {
currentEventSequence = mDumpAdapter.getEventSequenceByPosition(firstVisibleItemPosition);
}
mCurrentDecoderIndex = newDecoderIndex;
// the entire data set is changed, call notifyDataSetChanged
mDumpAdapter.notifyDataSetChanged();
// find the index of the current event in the new data set
if (currentEventSequence != -1) {
int pos = mDumpAdapter.findEventPositionBySequence(currentEventSequence);
pos = Math.min(Math.abs(pos), mDumpAdapter.getItemCount() - 1);
if (layoutManager.getStackFromEnd()) {
layoutManager.scrollToPositionWithOffset(pos, recyclerView.getHeight() - itemTopOffset);
} else {
layoutManager.scrollToPositionWithOffset(pos, itemTopOffset);
}
}
}

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_CURRENT_DECODER_INDEX, mCurrentDecoderIndex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ private void submitOperation() {
.show());
} else {
dismiss();
Snackbar.make(mBinding.getRoot(),
requireContext().getString(R.string.ui_toast_operation_success_v0s, result),
Snackbar.make(requireActivity().getWindow().getDecorView(),
requireContext().getString(R.string.ui_toast_operation_success_v0d, result),
Snackbar.LENGTH_SHORT).show();
}
});
Expand Down
Loading

0 comments on commit fc09005

Please sign in to comment.