Loading apps/demo/src/pages/logcat.tsx +25 −15 Original line number Diff line number Diff line import { ICommandBarItemProps, Stack, StackItem } from "@fluentui/react"; import { makeStyles, mergeClasses, shorthands } from "@griffel/react"; import { AbortController, decodeUtf8, ReadableStream, WritableStream } from '@yume-chan/adb'; import { Logcat, LogMessage, LogPriority } from '@yume-chan/android-bin'; import { AbortController, ReadableStream, WritableStream } from '@yume-chan/adb'; import { AndroidLogEntry, AndroidLogPriority, Logcat } from '@yume-chan/android-bin'; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; import { NextPage } from "next"; Loading Loading @@ -45,9 +45,8 @@ export interface Column extends GridColumn { title: string; } export interface LogRow extends LogMessage { export interface LogRow extends AndroidLogEntry { timeString?: string; payloadString?: string; } const state = makeAutoObservable({ Loading @@ -57,7 +56,7 @@ const state = makeAutoObservable({ flushRequested: false, list: [] as LogRow[], count: 0, stream: undefined as ReadableStream<LogMessage> | undefined, stream: undefined as ReadableStream<AndroidLogEntry> | undefined, stopSignal: undefined as AbortController | undefined, selectedCount: 0, animationFrameId: undefined as number | undefined, Loading Loading @@ -166,7 +165,7 @@ const state = makeAutoObservable({ } }, { width: 80, width: 60, title: 'PID', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; Loading @@ -181,7 +180,7 @@ const state = makeAutoObservable({ } }, { width: 80, width: 60, title: 'TID', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; Loading @@ -196,7 +195,7 @@ const state = makeAutoObservable({ } }, { width: 100, width: 80, title: 'Priority', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; Loading @@ -205,26 +204,37 @@ const state = makeAutoObservable({ return ( <div className={mergeClasses(classes.code, className)} {...rest}> {LogPriority[item.priority]} {AndroidLogPriority[item.priority]} </div> ); } }, { width: 300, flexGrow: 1, title: 'Payload', title: 'Tag', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; if (!item.payloadString) { item.payloadString = decodeUtf8(item.payload); } const classes = useClasses(); return ( <div className={mergeClasses(classes.code, className)} {...rest}> {item.payloadString} {item.tag} </div> ); } }, { width: 300, flexGrow: 1, title: 'Message', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; const classes = useClasses(); return ( <div className={mergeClasses(classes.code, className)} {...rest}> {item.message} </div> ); } Loading libraries/android-bin/src/demo-mode.ts +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ export enum DemoModeSignalStrength { Level4 = '4', } // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java;l=1073 // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java;l=1362;drc=3b775bf7ad89902f94e03d191b0d8fbdebf2bdbf export const DemoModeMobileDataTypes = ['1x', '3g', '4g', '4g+', '5g', '5ge', '5g+', 'e', 'g', 'h', 'h+', 'lte', 'lte+', 'dis', 'not', 'null'] as const; Loading libraries/android-bin/src/logcat.ts +39 −14 Original line number Diff line number Diff line // cspell: ignore logcat import { AdbCommandBase, AdbSubprocessNoneProtocol, BufferedStream, BufferedStreamEndedError, DecodeUtf8Stream, ReadableStream, SplitLineStream, WritableStream } from "@yume-chan/adb"; import Struct, { StructAsyncDeserializeStream } from "@yume-chan/struct"; import Struct, { decodeUtf8, StructAsyncDeserializeStream } from "@yume-chan/struct"; // `adb logcat` is an alias to `adb shell logcat` // so instead of adding to core library, it's implemented here Loading @@ -19,7 +19,8 @@ export enum LogId { Kernel, } export enum LogPriority { // https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/include/android/log.h;l=73;drc=82b5738732161dbaafb2e2f25cce19cd26b9157d export enum AndroidLogPriority { Unknown, Default, Verbose, Loading Loading @@ -56,21 +57,45 @@ export const LoggerEntry = export type LoggerEntry = typeof LoggerEntry['TDeserializeResult']; export interface LogMessage extends LoggerEntry { priority: LogPriority; payload: Uint8Array; // https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/logprint.cpp;drc=bbe77d66e7bee8bd1f0bc7e5492b5376b0207ef6;bpv=0 export interface AndroidLogEntry extends LoggerEntry { priority: AndroidLogPriority; tag: string; message: string; } export async function deserializeLogMessage(stream: StructAsyncDeserializeStream): Promise<LogMessage> { const entry = await LoggerEntry.deserialize(stream); function findTagEnd(payload: Uint8Array) { for (const separator of [0, ' '.charCodeAt(0), ':'.charCodeAt(0)]) { const index = payload.indexOf(separator); if (index !== -1) { return index; } } const index = payload.findIndex(x => x >= 0x7f); if (index !== -1) { return index; } return payload.length; } export async function deserializeAndroidLogEntry(stream: StructAsyncDeserializeStream): Promise<AndroidLogEntry> { const entry = await LoggerEntry.deserialize(stream) as unknown as AndroidLogEntry; if (entry.headerSize !== LoggerEntry.size) { await stream.read(entry.headerSize - LoggerEntry.size); } const priority = (await stream.read(1))[0] as LogPriority; const payload = await stream.read(entry.payloadSize - 1); (entry as any).priority = priority; (entry as any).payload = payload; return entry as LogMessage; let payload = await stream.read(entry.payloadSize); // https://cs.android.com/android/platform/superproject/+/master:system/logging/logcat/logcat.cpp;l=193-194;drc=bbe77d66e7bee8bd1f0bc7e5492b5376b0207ef6 // TODO: payload for some log IDs are in binary format. entry.priority = payload[0] as AndroidLogPriority; payload = payload.subarray(1); const tagEnd = findTagEnd(payload); entry.tag = decodeUtf8(payload.subarray(0, tagEnd)); entry.message = tagEnd < payload.length - 1 ? decodeUtf8(payload.subarray(tagEnd + 1)) : ''; return entry; } export interface LogSize { Loading Loading @@ -158,7 +183,7 @@ export class Logcat extends AdbCommandBase { ]); } public binary(options?: LogcatOptions): ReadableStream<LogMessage> { public binary(options?: LogcatOptions): ReadableStream<AndroidLogEntry> { let bufferedStream: BufferedStream; return new ReadableStream({ start: async () => { Loading @@ -175,7 +200,7 @@ export class Logcat extends AdbCommandBase { }, async pull(controller) { try { const entry = await deserializeLogMessage(bufferedStream); const entry = await deserializeAndroidLogEntry(bufferedStream); controller.enqueue(entry); } catch (e) { if (e instanceof BufferedStreamEndedError) { Loading Loading
apps/demo/src/pages/logcat.tsx +25 −15 Original line number Diff line number Diff line import { ICommandBarItemProps, Stack, StackItem } from "@fluentui/react"; import { makeStyles, mergeClasses, shorthands } from "@griffel/react"; import { AbortController, decodeUtf8, ReadableStream, WritableStream } from '@yume-chan/adb'; import { Logcat, LogMessage, LogPriority } from '@yume-chan/android-bin'; import { AbortController, ReadableStream, WritableStream } from '@yume-chan/adb'; import { AndroidLogEntry, AndroidLogPriority, Logcat } from '@yume-chan/android-bin'; import { action, autorun, makeAutoObservable, observable, runInAction } from "mobx"; import { observer } from "mobx-react-lite"; import { NextPage } from "next"; Loading Loading @@ -45,9 +45,8 @@ export interface Column extends GridColumn { title: string; } export interface LogRow extends LogMessage { export interface LogRow extends AndroidLogEntry { timeString?: string; payloadString?: string; } const state = makeAutoObservable({ Loading @@ -57,7 +56,7 @@ const state = makeAutoObservable({ flushRequested: false, list: [] as LogRow[], count: 0, stream: undefined as ReadableStream<LogMessage> | undefined, stream: undefined as ReadableStream<AndroidLogEntry> | undefined, stopSignal: undefined as AbortController | undefined, selectedCount: 0, animationFrameId: undefined as number | undefined, Loading Loading @@ -166,7 +165,7 @@ const state = makeAutoObservable({ } }, { width: 80, width: 60, title: 'PID', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; Loading @@ -181,7 +180,7 @@ const state = makeAutoObservable({ } }, { width: 80, width: 60, title: 'TID', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; Loading @@ -196,7 +195,7 @@ const state = makeAutoObservable({ } }, { width: 100, width: 80, title: 'Priority', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; Loading @@ -205,26 +204,37 @@ const state = makeAutoObservable({ return ( <div className={mergeClasses(classes.code, className)} {...rest}> {LogPriority[item.priority]} {AndroidLogPriority[item.priority]} </div> ); } }, { width: 300, flexGrow: 1, title: 'Payload', title: 'Tag', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; if (!item.payloadString) { item.payloadString = decodeUtf8(item.payload); } const classes = useClasses(); return ( <div className={mergeClasses(classes.code, className)} {...rest}> {item.payloadString} {item.tag} </div> ); } }, { width: 300, flexGrow: 1, title: 'Message', CellComponent: ({ rowIndex, columnIndex, className, ...rest }) => { const item = this.list[rowIndex]; const classes = useClasses(); return ( <div className={mergeClasses(classes.code, className)} {...rest}> {item.message} </div> ); } Loading
libraries/android-bin/src/demo-mode.ts +1 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ export enum DemoModeSignalStrength { Level4 = '4', } // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java;l=1073 // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java;l=1362;drc=3b775bf7ad89902f94e03d191b0d8fbdebf2bdbf export const DemoModeMobileDataTypes = ['1x', '3g', '4g', '4g+', '5g', '5ge', '5g+', 'e', 'g', 'h', 'h+', 'lte', 'lte+', 'dis', 'not', 'null'] as const; Loading
libraries/android-bin/src/logcat.ts +39 −14 Original line number Diff line number Diff line // cspell: ignore logcat import { AdbCommandBase, AdbSubprocessNoneProtocol, BufferedStream, BufferedStreamEndedError, DecodeUtf8Stream, ReadableStream, SplitLineStream, WritableStream } from "@yume-chan/adb"; import Struct, { StructAsyncDeserializeStream } from "@yume-chan/struct"; import Struct, { decodeUtf8, StructAsyncDeserializeStream } from "@yume-chan/struct"; // `adb logcat` is an alias to `adb shell logcat` // so instead of adding to core library, it's implemented here Loading @@ -19,7 +19,8 @@ export enum LogId { Kernel, } export enum LogPriority { // https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/include/android/log.h;l=73;drc=82b5738732161dbaafb2e2f25cce19cd26b9157d export enum AndroidLogPriority { Unknown, Default, Verbose, Loading Loading @@ -56,21 +57,45 @@ export const LoggerEntry = export type LoggerEntry = typeof LoggerEntry['TDeserializeResult']; export interface LogMessage extends LoggerEntry { priority: LogPriority; payload: Uint8Array; // https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/logprint.cpp;drc=bbe77d66e7bee8bd1f0bc7e5492b5376b0207ef6;bpv=0 export interface AndroidLogEntry extends LoggerEntry { priority: AndroidLogPriority; tag: string; message: string; } export async function deserializeLogMessage(stream: StructAsyncDeserializeStream): Promise<LogMessage> { const entry = await LoggerEntry.deserialize(stream); function findTagEnd(payload: Uint8Array) { for (const separator of [0, ' '.charCodeAt(0), ':'.charCodeAt(0)]) { const index = payload.indexOf(separator); if (index !== -1) { return index; } } const index = payload.findIndex(x => x >= 0x7f); if (index !== -1) { return index; } return payload.length; } export async function deserializeAndroidLogEntry(stream: StructAsyncDeserializeStream): Promise<AndroidLogEntry> { const entry = await LoggerEntry.deserialize(stream) as unknown as AndroidLogEntry; if (entry.headerSize !== LoggerEntry.size) { await stream.read(entry.headerSize - LoggerEntry.size); } const priority = (await stream.read(1))[0] as LogPriority; const payload = await stream.read(entry.payloadSize - 1); (entry as any).priority = priority; (entry as any).payload = payload; return entry as LogMessage; let payload = await stream.read(entry.payloadSize); // https://cs.android.com/android/platform/superproject/+/master:system/logging/logcat/logcat.cpp;l=193-194;drc=bbe77d66e7bee8bd1f0bc7e5492b5376b0207ef6 // TODO: payload for some log IDs are in binary format. entry.priority = payload[0] as AndroidLogPriority; payload = payload.subarray(1); const tagEnd = findTagEnd(payload); entry.tag = decodeUtf8(payload.subarray(0, tagEnd)); entry.message = tagEnd < payload.length - 1 ? decodeUtf8(payload.subarray(tagEnd + 1)) : ''; return entry; } export interface LogSize { Loading Loading @@ -158,7 +183,7 @@ export class Logcat extends AdbCommandBase { ]); } public binary(options?: LogcatOptions): ReadableStream<LogMessage> { public binary(options?: LogcatOptions): ReadableStream<AndroidLogEntry> { let bufferedStream: BufferedStream; return new ReadableStream({ start: async () => { Loading @@ -175,7 +200,7 @@ export class Logcat extends AdbCommandBase { }, async pull(controller) { try { const entry = await deserializeLogMessage(bufferedStream); const entry = await deserializeAndroidLogEntry(bufferedStream); controller.enqueue(entry); } catch (e) { if (e instanceof BufferedStreamEndedError) { Loading