From 617ad1d5e9b7aa193471187e3f225a6e9db40dba Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Mon, 19 Sep 2022 23:29:18 +0300 Subject: [PATCH 01/43] play with package info --- .../Editor/AndroidLogcatPackageInfoTests.cs | 113 ++++++++++++++++++ .../AndroidLogcatPackageInfoTests.cs.meta | 11 ++ 2 files changed, 124 insertions(+) create mode 100644 com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs create mode 100644 com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs.meta diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs new file mode 100644 index 00000000..e6a4128d --- /dev/null +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs @@ -0,0 +1,113 @@ +using System.Collections.Generic; +using NUnit.Framework; +using System.Text.RegularExpressions; +using Unity.Android.Logcat; +using System.Linq; +using System.Text; + +class AndroidLogcatPacakgeInfoTests +{ + [Test] + public void CanParsePackageInfo() + { + var contents = @" Package [com.DefaultCompany.AndroidEmptyGameActivity] (ffc5f27): + userId=10198 + pkg=Package{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} + codePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== + resourcePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== + legacyNativeLibraryDir=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ==/lib + primaryCpuAbi=armeabi-v7a + secondaryCpuAbi=null + versionCode=1 minSdk=22 targetSdk=32 + versionName=0.1 + splits=[base] + apkSigningVersion=2 + applicationInfo=ApplicationInfo{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} + flags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] + privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ] + forceQueryable=false + queriesPackages=[] + dataDir=/data/user/0/com.DefaultCompany.AndroidEmptyGameActivity + supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity] + timeStamp=2022-09-19 15:52:25 + firstInstallTime=2022-09-13 16:14:57 + lastUpdateTime=2022-09-19 15:52:26 + signatures=PackageSignatures{af06a3b version:2, signatures:[ca97cd1f], past signatures:[]} + installPermissionsFixed=true + pkgFlags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] + requested permissions: + android.permission.INTERNET + android.permission.ACCESS_NETWORK_STATE + install permissions: + android.permission.INTERNET: granted=true + android.permission.ACCESS_NETWORK_STATE: granted=true + User 0: ceDataInode=311793 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false + gids=[3003] + runtime permissions: +"; + + var errors = new StringBuilder(); + var lines = contents.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries).Select(s => s.TrimStart()).ToArray(); + + if (lines.Length == 0) + throw new System.Exception("No package info found"); + var packageName = Regex.Escape("com.DefaultCompany.AndroidEmptyGameActivity"); + var title = new Regex($"Package.*{packageName}.*\\:"); + + if (!title.Match(lines[0]).Success) + throw new System.Exception($"Expected 'Package [] () :', but got '{lines[0]}'"); + + var keyValueRegex = new Regex(@"(?\S+)\=(?.*)"); + for (int i = 1; i < lines.Length; i++) + { + var l = lines[i]; + // Check if next lines are list + while (l.EndsWith("permissions:")) + { + UnityEngine.Debug.Log($"{l}"); + i++; + // List permissions + while (i < lines.Length) + { + var entry = lines[i]; + if (entry.StartsWith("android.permission")) + { + UnityEngine.Debug.Log($"P--> {entry}"); + i++; + } + else + { + l = lines[i]; + break; + } + } + + if (i >= lines.Length) + break; + } + + if (i >= lines.Length) + break; + + var result = keyValueRegex.Match(l); + + if (result.Success) + { + var key = result.Groups["key"]; + var value = result.Groups["value"]; + + UnityEngine.Debug.Log($"{key}={value}"); + continue; + } + + + errors.AppendLine($"Failed to resolve {l}"); + } + + if (errors.Length > 0) + { + UnityEngine.Debug.LogError($"Found errors:\n{errors.ToString()}\n\nin\n{contents}"); + } + + } +} diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs.meta b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs.meta new file mode 100644 index 00000000..ca5c049f --- /dev/null +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 16c4f2eeca40daa408c529880a726667 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 61fe741dd0a0e35a0dce6726564341dfe07dc43f Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Tue, 20 Sep 2022 09:19:32 +0300 Subject: [PATCH 02/43] bump version --- com.unity.mobile.android-logcat/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.mobile.android-logcat/package.json b/com.unity.mobile.android-logcat/package.json index 00c85baf..6fcd6d7f 100644 --- a/com.unity.mobile.android-logcat/package.json +++ b/com.unity.mobile.android-logcat/package.json @@ -1,8 +1,8 @@ { "name": "com.unity.mobile.android-logcat", "displayName": "Android Logcat", - "version": "1.3.2", - "unity": "2019.4", + "version": "1.3.3", + "unity": "2022.2", "description": "Android Logcat package provides support for:\n - Android log messages\n - Android application memory statistics\n - Android Screen Capture\n - Android Screen Recorder\n - Stacktrace Utility\n\nClick the 'View documentation' link above for more information.\n\nThe window can be accessed in Unity Editor via 'Window > Analysis > Android Logcat', or simply by pressing 'Alt+6' on Windows or 'Option+6' on macOS. \n\nMake sure to have Android module loaded and switch to Android build target in 'Build Settings' window if the menu doesn't exist.", "keywords": ["Mobile", "Android", "Logcat"], "dependencies": { From bbec71f9be14803ca80da2d6ae8db19864d743a4 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 15 Oct 2022 00:05:06 +0300 Subject: [PATCH 03/43] WIP --- .../Editor/AndroidLogcatPackageEntry.cs | 12 ++ .../Editor/AndroidLogcatPackageEntry.cs.meta | 11 ++ .../Editor/AndroidLogcatPackagesWindow.cs | 40 +++++ .../AndroidLogcatPackagesWindow.cs.meta | 11 ++ .../Editor/UI/AndroidLogcatPackageListView.cs | 153 ++++++++++++++++++ .../UI/AndroidLogcatPackageListView.cs.meta | 11 ++ .../UI/AndroidLogcatPackageListViewItem.cs | 17 ++ .../AndroidLogcatPackageListViewItem.cs.meta | 11 ++ .../UI/AndroidLogcatPackageListViewState.cs | 117 ++++++++++++++ .../AndroidLogcatPackageListViewState.cs.meta | 11 ++ 10 files changed, 394 insertions(+) create mode 100644 com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs create mode 100644 com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs.meta create mode 100644 com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs create mode 100644 com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs.meta create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs new file mode 100644 index 00000000..0cb20c32 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs @@ -0,0 +1,12 @@ +using System; + +namespace Unity.Android.Logcat +{ + [Serializable] + internal class PackageEntry + { + public string Name { set; get; } + + internal int GetId() => GetHashCode(); + } +} diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs.meta b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs.meta new file mode 100644 index 00000000..9a9f6754 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee72d8225fceb2346b59c264f5d61964 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs new file mode 100644 index 00000000..8545c0f0 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Unity.Android.Logcat +{ + // adb shell cmd package list packages -3 -U -i + + internal class AndroidLogcatPackagesWindow : EditorWindow + { + AndroidLogcatPackageListView m_View; + AndroidLogcatPackageListViewState m_State; + [MenuItem("Window/My Window")] + static void Init() + { + // Get existing open window or if none, make a new one: + AndroidLogcatPackagesWindow window = (AndroidLogcatPackagesWindow)EditorWindow.GetWindow(typeof(AndroidLogcatPackagesWindow)); + window.Show(); + } + + private void OnEnable() + { + m_State = AndroidLogcatPackageListViewState.CreateOrInitializeTreeState(m_State); + var items = new List(); + items.Add(new PackageEntry() { Name = "Hello" }); + items.Add(new PackageEntry() { Name = "Hello2" }); + m_View = new AndroidLogcatPackageListView(m_State, items); + } + + void OnGUI() + { + var rc = new Rect(0, 0, Screen.width, Screen.height); + if (m_View != null) + m_View.OnGUI(rc); + else + GUILayout.Label("Package View failed to create"); + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs.meta b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs.meta new file mode 100644 index 00000000..e4fcdaad --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0e599f21ead36c74ba0a79a6851f350b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs new file mode 100644 index 00000000..cd3e060b --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.IMGUI.Controls; +using UnityEngine; + +namespace Unity.Android.Logcat +{ + // Note: UI Toolkit MulticolumnListView is not available in 2020 + internal class AndroidLogcatPackageListView : TreeView + { + internal static class Styles + { + internal static GUIStyle buildSettingsButton = new GUIStyle(EditorStyles.miniButton) { alignment = TextAnchor.MiddleLeft }; + } + + private Dictionary m_CachedRowMap = new Dictionary(); + private IReadOnlyList m_Entries; + + public AndroidLogcatPackageListView(AndroidLogcatPackageListViewState state, IReadOnlyList entries) + : base(state.treeViewState, state.columnHeader) + { + m_Entries = entries; + + rowHeight = 20f; + showAlternatingRowBackgrounds = true; + showBorder = true; + customFoldoutYOffset = (rowHeight - EditorGUIUtility.singleLineHeight) * 0.5f; + extraSpaceBeforeIconAndLabel = 18f; + + + Reload(); + } + + protected override TreeViewItem BuildRoot() + { + return new TreeViewItem(0, -1); + } + + protected override IList BuildRows(TreeViewItem root) + { + var items = new List(); + foreach (var e in m_Entries) + { + items.Add(new AndroidLogcatPackageListItem(0, e)); + } + return items; + /* + var tempRoot = new AndroidLogcatPackageListItem(-1, null); + + foreach (var e in m_Entries) + { + tempRoot.AddChild(new AndroidLogcatPackageListItem(0, e)); + } + + var items = new List(); + AddChildrenRecursive(tempRoot, -1, items); + + SetupParentsAndChildrenFromDepths(root, items); + return items; + */ + } + + /* + void AddChildrenRecursive(TreeViewItem parent, int depth, IList newRows) + { + if (parent == null || !parent.hasChildren) + return; + + if (parent.children == null) + { + var fileTreeView = (AndroidLogcatPackageListItem)parent; + var childs = m_QueryChilds(fileTreeView.DeviceExplorerEntry, parent.depth + 1); + foreach (var c in childs) + { + parent.AddChild(c); + } + } + + if (parent.children == null) + return; + + foreach (AndroidLogcatPackageListItem child in parent.children) + { + var item = new AndroidLogcatPackageListItem(child.depth, child.DeviceExplorerEntry); + newRows.Add(child); + + if (child.hasChildren) + { + if (IsExpanded(child.id)) + { + AddChildrenRecursive(child, depth + 1, newRows); + } + else + { + item.children = CreateChildListForCollapsedParent(); + } + } + } + } + */ + + protected override void RowGUI(RowGUIArgs args) + { + var item = (AndroidLogcatPackageListItem)args.item; + for (int i = 0; i < args.GetNumVisibleColumns(); ++i) + { + Rect rc = args.GetCellRect(i); + if (i == columnIndexForTreeFoldouts) + { + var indent = GetContentIndent(item); + rc.x += indent; + rc.width -= indent; + } + DisplayItem(item, i, rc); + } + } + + private void DisplayItem(AndroidLogcatPackageListItem item, int c, Rect rc) + { + AndroidLogcatPackageListViewState.Columns column = (AndroidLogcatPackageListViewState.Columns)c; + + var props = item.PackageEntry; + EditorGUI.BeginChangeCheck(); + switch (column) + { + case AndroidLogcatPackageListViewState.Columns.Type: + GUI.Label(rc, "Bla"); + + break; + case AndroidLogcatPackageListViewState.Columns.PackageName: + GUI.Label(rc, new GUIContent(props.Name, props.Name)); + + break; + /* + case AndroidLogcatPackageListViewState.Columns.Permissions: + GUI.Label(rc, props.Permissions); + //props.Build = EditorGUI.Toggle(rc, props.Build); + break; + case AndroidLogcatPackageListViewState.Columns.Date: + GUI.Label(rc, props.DateModified.ToString("yyyy-MM-dd HH:mm:ss")); + break; + case AndroidLogcatPackageListViewState.Columns.Size: + GUI.Label(rc, $"{props.Size.ToString()}B"); + break; + */ + } + + if (EditorGUI.EndChangeCheck()) + this.SetSelection(new List(new[] { props.GetId() }), TreeViewSelectionOptions.None); + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta new file mode 100644 index 00000000..5e9b16df --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21dfae1ceb4c16745a6b9c172407e30c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs new file mode 100644 index 00000000..dc72b0e4 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs @@ -0,0 +1,17 @@ +using UnityEditor.IMGUI.Controls; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackageListItem : TreeViewItem + { + internal PackageEntry PackageEntry { get; } + + internal AndroidLogcatPackageListItem(int depth, PackageEntry entry) + : base(entry.GetId(), depth) + { + PackageEntry = entry; + } + + public override bool hasChildren => false; + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta new file mode 100644 index 00000000..9a109567 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3e55ab3ff10b724a809adeb77a2af8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs new file mode 100644 index 00000000..80ba2822 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.IMGUI.Controls; +using UnityEngine; +using UnityEngine.Assertions; + +namespace Unity.Android.Logcat +{ + // Note: UI Toolkit MulticolumnListView is not available in 2020 + [Serializable] + internal class AndroidLogcatPackageListViewState + { + internal enum Columns + { + PackageName, + Type, + /* + Permissions, + Date, + Size + */ + } + + [SerializeField] + internal TreeViewState treeViewState; + + [SerializeField] + internal MultiColumnHeaderState columnHeaderState; + + [NonSerialized] + internal MultiColumnHeader columnHeader; + + internal static AndroidLogcatPackageListViewState CreateOrInitializeTreeState(AndroidLogcatPackageListViewState state = null) + { + if (state == null) + state = new AndroidLogcatPackageListViewState(); + + if (state.treeViewState == null) + state.treeViewState = new TreeViewState(); + + bool firstInit = state.columnHeaderState == null; + var headerState = CreateMultiColumnHeaderState(); + if (MultiColumnHeaderState.CanOverwriteSerializedFields(state.columnHeaderState, headerState)) + MultiColumnHeaderState.OverwriteSerializedFields(state.columnHeaderState, headerState); + state.columnHeaderState = headerState; + + state.columnHeader = new MultiColumnHeader(headerState); + if (firstInit) + state.columnHeader.ResizeToFit(); + + return state; + } + + private static MultiColumnHeaderState CreateMultiColumnHeaderState() + { + var columns = new[] + { + new MultiColumnHeaderState.Column + { + headerContent = new GUIContent("Package Name"), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = 200, + minWidth = 200, + autoResize = true, + allowToggleVisibility = false + }, + new MultiColumnHeaderState.Column + { + headerContent = new GUIContent("Type"), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = 200, + minWidth = 200, + autoResize = false, + allowToggleVisibility = false + }/*, + new MultiColumnHeaderState.Column + { + headerContent = new GUIContent("Permissions"), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = 100, + minWidth = 100, + autoResize = false, + allowToggleVisibility = false + }, + new MultiColumnHeaderState.Column + { + headerContent = new GUIContent("Date"), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = 100, + minWidth = 100, + autoResize = false, + allowToggleVisibility = false + }, + new MultiColumnHeaderState.Column + { + headerContent = new GUIContent("Size"), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = 100, + minWidth = 100, + autoResize = false, + allowToggleVisibility = false + }*/ + }; + + Assert.AreEqual(columns.Length, Enum.GetValues(typeof(Columns)).Length, "Number of columns should match number of enum values: You probably forgot to update one of them."); + + var header = new MultiColumnHeaderState(columns); + return header; + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta new file mode 100644 index 00000000..d49fbfc7 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3ce8489378c95c42984e319a8b859ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 853e780470e296202992828620d06bd979903b72 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 15 Oct 2022 18:39:25 +0300 Subject: [PATCH 04/43] List package entries --- .../Editor/AndroidLogcatPackageEntry.cs | 2 + .../Editor/AndroidLogcatPackagesWindow.cs | 6 +-- .../Editor/AndroidLogcatUtilities.cs | 44 +++++++++++++++++++ .../Editor/UI/AndroidLogcatPackageListView.cs | 13 ++++-- .../UI/AndroidLogcatPackageListViewState.cs | 34 +++----------- 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs index 0cb20c32..420869e0 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs @@ -6,6 +6,8 @@ namespace Unity.Android.Logcat internal class PackageEntry { public string Name { set; get; } + public string Installer { set; get; } + public string UID { set; get; } internal int GetId() => GetHashCode(); } diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 8545c0f0..7bbe890b 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -22,10 +22,8 @@ static void Init() private void OnEnable() { m_State = AndroidLogcatPackageListViewState.CreateOrInitializeTreeState(m_State); - var items = new List(); - items.Add(new PackageEntry() { Name = "Hello" }); - items.Add(new PackageEntry() { Name = "Hello2" }); - m_View = new AndroidLogcatPackageListView(m_State, items); + var packages = AndroidLogcatUtilities.RetrievePackages(AndroidLogcatManager.instance.Runtime.Tools.ADB, AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice); + m_View = new AndroidLogcatPackageListView(m_State, packages); } void OnGUI() diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs index 39c4e773..64760d14 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs @@ -199,6 +199,50 @@ public static string GetPackageNameFromPid(AndroidBridge.ADB adb, IAndroidLogcat } } + public static PackageEntry[] RetrievePackages(AndroidBridge.ADB adb, IAndroidLogcatDevice device) + { + if (device == null) + return Array.Empty(); + + try + { + var cmd = $"-s {device.Id} shell cmd package list packages -3 -U -i"; + AndroidLogcatInternalLog.Log("{0} {1}", adb.GetADBPath(), cmd); + var output = adb.Run(new[] { cmd }, "Unable to retrieve packages"); + + if (string.IsNullOrEmpty(output)) + return Array.Empty(); + + var entries = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var packages = new List(); + var regex = new Regex(@"package:(?\S+)\s+installer=(?\S+)\s+uid:(?\S+)"); + foreach (var e in entries) + { + var result = regex.Match(e); + if (result.Success) + { + packages.Add(new PackageEntry() + { + Name = result.Groups["name"].Value, + Installer = result.Groups["installer"].Value, + UID = result.Groups["uid"].Value + }); + } + else + { + AndroidLogcatInternalLog.Log($"Failed to parse package info:\n{e}"); + } + } + + return packages.ToArray(); + } + catch (Exception ex) + { + AndroidLogcatInternalLog.Log(ex.Message); + return Array.Empty(); + } + } + /// /// Return the detail info of the given device. /// diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs index cd3e060b..a77d0940 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs @@ -124,14 +124,19 @@ private void DisplayItem(AndroidLogcatPackageListItem item, int c, Rect rc) EditorGUI.BeginChangeCheck(); switch (column) { - case AndroidLogcatPackageListViewState.Columns.Type: - GUI.Label(rc, "Bla"); - - break; case AndroidLogcatPackageListViewState.Columns.PackageName: GUI.Label(rc, new GUIContent(props.Name, props.Name)); break; + case AndroidLogcatPackageListViewState.Columns.UniqueIdentifier: + GUI.Label(rc, new GUIContent(props.UID)); + + break; + case AndroidLogcatPackageListViewState.Columns.Installer: + GUI.Label(rc, new GUIContent(props.Installer)); + + break; + /* case AndroidLogcatPackageListViewState.Columns.Permissions: GUI.Label(rc, props.Permissions); diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs index 80ba2822..0441606e 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs @@ -14,12 +14,8 @@ internal class AndroidLogcatPackageListViewState internal enum Columns { PackageName, - Type, - /* - Permissions, - Date, - Size - */ + UniqueIdentifier, + Installer } [SerializeField] @@ -68,44 +64,24 @@ private static MultiColumnHeaderState CreateMultiColumnHeaderState() }, new MultiColumnHeaderState.Column { - headerContent = new GUIContent("Type"), + headerContent = new GUIContent("UID", "Unique Identifier"), headerTextAlignment = TextAlignment.Left, canSort = false, width = 200, minWidth = 200, autoResize = false, allowToggleVisibility = false - }/*, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Permissions"), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = 100, - minWidth = 100, - autoResize = false, - allowToggleVisibility = false - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Date"), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = 100, - minWidth = 100, - autoResize = false, - allowToggleVisibility = false }, new MultiColumnHeaderState.Column { - headerContent = new GUIContent("Size"), + headerContent = new GUIContent("Installer", "The installer application"), headerTextAlignment = TextAlignment.Left, canSort = false, width = 100, minWidth = 100, autoResize = false, allowToggleVisibility = false - }*/ + } }; Assert.AreEqual(columns.Length, Enum.GetValues(typeof(Columns)).Length, "Number of columns should match number of enum values: You probably forgot to update one of them."); From 7984648b6fb184c0dd758f68e063bd064bf073da Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 15 Oct 2022 20:21:10 +0300 Subject: [PATCH 05/43] WIP --- .../Editor/AndroidLogcatPackageEntry.cs | 36 ++++++++ .../Editor/AndroidLogcatPackagesWindow.cs | 17 +++- .../Editor/UI/AndroidLogcatPackageListView.cs | 85 ++++++------------- .../UI/AndroidLogcatPackageListViewState.cs | 25 ++++-- 4 files changed, 96 insertions(+), 67 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs index 420869e0..a90de5a5 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs @@ -10,5 +10,41 @@ internal class PackageEntry public string UID { set; get; } internal int GetId() => GetHashCode(); + + internal void Launch() + { + var adb = AndroidLogcatManager.instance.Runtime.Tools.ADB; + var device = AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice; + // Not using 'shell am start' since it requires knowing the activity name + var cmd = $"-s {device.Id} shell monkey -p {Name} -c android.intent.category.LAUNCHER 1"; + var output = adb.Run(new[] { cmd }, "Unable to launch package"); + UnityEngine.Debug.Log(output); + } + internal void Pause() + { + var adb = AndroidLogcatManager.instance.Runtime.Tools.ADB; + var device = AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice; + var cmd = $"-s {device.Id} shell input keyevent 3"; + var output = adb.Run(new[] { cmd }, "Unable to pause the package"); + UnityEngine.Debug.Log(output); + } + + internal void Stop() + { + var adb = AndroidLogcatManager.instance.Runtime.Tools.ADB; + var device = AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice; + var cmd = $"-s {device.Id} shell am force-stop {Name}"; + var output = adb.Run(new[] { cmd }, "Unable to stop package"); + UnityEngine.Debug.Log(output); + } + + internal void Uninstall() + { + var adb = AndroidLogcatManager.instance.Runtime.Tools.ADB; + var device = AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice; + var cmd = $"-s {device.Id} uninstall {Name}"; + var output = adb.Run(new[] { cmd }, "Unable to uninstall the package"); + UnityEngine.Debug.Log(output); + } } } diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 7bbe890b..38671123 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -22,17 +22,28 @@ static void Init() private void OnEnable() { m_State = AndroidLogcatPackageListViewState.CreateOrInitializeTreeState(m_State); - var packages = AndroidLogcatUtilities.RetrievePackages(AndroidLogcatManager.instance.Runtime.Tools.ADB, AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice); - m_View = new AndroidLogcatPackageListView(m_State, packages); + m_View = new AndroidLogcatPackageListView(m_State, GetPackageEntries()); + } + + PackageEntry[] GetPackageEntries() + { + return AndroidLogcatUtilities.RetrievePackages( + AndroidLogcatManager.instance.Runtime.Tools.ADB, + AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice); } void OnGUI() { - var rc = new Rect(0, 0, Screen.width, Screen.height); + if (GUILayout.Button("Reload")) + m_View.Reload(GetPackageEntries()); + var rc = GUILayoutUtility.GetRect(new GUIContent(""), GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); if (m_View != null) m_View.OnGUI(rc); else GUILayout.Label("Package View failed to create"); + + if (m_View.RequiresUpdating) + m_View.Reload(GetPackageEntries()); } } } diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs index a77d0940..b2efa175 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs @@ -15,7 +15,8 @@ internal static class Styles } private Dictionary m_CachedRowMap = new Dictionary(); - private IReadOnlyList m_Entries; + public IReadOnlyList m_Entries; + public bool RequiresUpdating { set; get; } public AndroidLogcatPackageListView(AndroidLogcatPackageListViewState state, IReadOnlyList entries) : base(state.treeViewState, state.columnHeader) @@ -27,8 +28,6 @@ public AndroidLogcatPackageListView(AndroidLogcatPackageListViewState state, IRe showBorder = true; customFoldoutYOffset = (rowHeight - EditorGUIUtility.singleLineHeight) * 0.5f; extraSpaceBeforeIconAndLabel = 18f; - - Reload(); } @@ -39,66 +38,15 @@ protected override TreeViewItem BuildRoot() protected override IList BuildRows(TreeViewItem root) { + Debug.Log("Build Rows"); var items = new List(); foreach (var e in m_Entries) { items.Add(new AndroidLogcatPackageListItem(0, e)); } return items; - /* - var tempRoot = new AndroidLogcatPackageListItem(-1, null); - - foreach (var e in m_Entries) - { - tempRoot.AddChild(new AndroidLogcatPackageListItem(0, e)); - } - - var items = new List(); - AddChildrenRecursive(tempRoot, -1, items); - - SetupParentsAndChildrenFromDepths(root, items); - return items; - */ - } - - /* - void AddChildrenRecursive(TreeViewItem parent, int depth, IList newRows) - { - if (parent == null || !parent.hasChildren) - return; - - if (parent.children == null) - { - var fileTreeView = (AndroidLogcatPackageListItem)parent; - var childs = m_QueryChilds(fileTreeView.DeviceExplorerEntry, parent.depth + 1); - foreach (var c in childs) - { - parent.AddChild(c); - } - } - - if (parent.children == null) - return; - foreach (AndroidLogcatPackageListItem child in parent.children) - { - var item = new AndroidLogcatPackageListItem(child.depth, child.DeviceExplorerEntry); - newRows.Add(child); - - if (child.hasChildren) - { - if (IsExpanded(child.id)) - { - AddChildrenRecursive(child, depth + 1, newRows); - } - else - { - item.children = CreateChildListForCollapsedParent(); - } - } - } } - */ protected override void RowGUI(RowGUIArgs args) { @@ -126,14 +74,30 @@ private void DisplayItem(AndroidLogcatPackageListItem item, int c, Rect rc) { case AndroidLogcatPackageListViewState.Columns.PackageName: GUI.Label(rc, new GUIContent(props.Name, props.Name)); - break; case AndroidLogcatPackageListViewState.Columns.UniqueIdentifier: GUI.Label(rc, new GUIContent(props.UID)); - break; case AndroidLogcatPackageListViewState.Columns.Installer: GUI.Label(rc, new GUIContent(props.Installer)); + break; + case AndroidLogcatPackageListViewState.Columns.Operations: + var rcSplit = new Rect(rc.x, rc.y, rc.width * 0.25f, rc.height); + if (GUI.Button(rcSplit, new GUIContent("Launch"))) + props.Launch(); + rcSplit.x += rcSplit.width; + if (GUI.Button(rcSplit, new GUIContent("Pause"))) + props.Pause(); + rcSplit.x += rcSplit.width; + if (GUI.Button(rcSplit, new GUIContent("Stop"))) + props.Stop(); + rcSplit.x += rcSplit.width; + if (GUI.Button(rcSplit, new GUIContent("Uninstall"))) + { + // TODO: Dialog asking are you sure + props.Uninstall(); + RequiresUpdating = true; + } break; @@ -154,5 +118,12 @@ private void DisplayItem(AndroidLogcatPackageListItem item, int c, Rect rc) if (EditorGUI.EndChangeCheck()) this.SetSelection(new List(new[] { props.GetId() }), TreeViewSelectionOptions.None); } + + public void Reload(IReadOnlyList entries) + { + m_Entries = entries; + Reload(); + RequiresUpdating = false; + } } } diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs index 0441606e..6ef1cdf7 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs @@ -14,8 +14,9 @@ internal class AndroidLogcatPackageListViewState internal enum Columns { PackageName, + Installer, UniqueIdentifier, - Installer + Operations } [SerializeField] @@ -57,29 +58,39 @@ private static MultiColumnHeaderState CreateMultiColumnHeaderState() headerContent = new GUIContent("Package Name"), headerTextAlignment = TextAlignment.Left, canSort = false, - width = 200, + width = 250, minWidth = 200, autoResize = true, allowToggleVisibility = false }, new MultiColumnHeaderState.Column { - headerContent = new GUIContent("UID", "Unique Identifier"), + headerContent = new GUIContent("Installer", "The installer application"), headerTextAlignment = TextAlignment.Left, canSort = false, width = 200, minWidth = 200, - autoResize = false, + autoResize = true, allowToggleVisibility = false }, new MultiColumnHeaderState.Column { - headerContent = new GUIContent("Installer", "The installer application"), + headerContent = new GUIContent("UID", "Unique Identifier"), headerTextAlignment = TextAlignment.Left, canSort = false, - width = 100, + width = 50, + minWidth = 50, + autoResize = true, + allowToggleVisibility = false + }, + new MultiColumnHeaderState.Column + { + headerContent = new GUIContent("Operations"), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = 200, minWidth = 100, - autoResize = false, + autoResize = true, allowToggleVisibility = false } }; From 34976e0dbd8d0f48e186724d2888df112b034f48 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Fri, 18 Nov 2022 21:15:42 +0200 Subject: [PATCH 06/43] rename --- ...ewItem.cs => AndroidLogcatListViewItem.cs} | 4 +- ...meta => AndroidLogcatListViewItem.cs.meta} | 2 +- .../Editor/UI/AndroidLogcatListViewState.cs | 80 ++++++++++++++ ...eta => AndroidLogcatListViewState.cs.meta} | 2 +- .../UI/AndroidLogcatPackageListViewState.cs | 104 ------------------ 5 files changed, 84 insertions(+), 108 deletions(-) rename com.unity.mobile.android-logcat/Editor/UI/{AndroidLogcatPackageListViewItem.cs => AndroidLogcatListViewItem.cs} (72%) rename com.unity.mobile.android-logcat/Editor/UI/{AndroidLogcatPackageListViewItem.cs.meta => AndroidLogcatListViewItem.cs.meta} (83%) create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs rename com.unity.mobile.android-logcat/Editor/UI/{AndroidLogcatPackageListViewState.cs.meta => AndroidLogcatListViewState.cs.meta} (83%) delete mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs similarity index 72% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs rename to com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs index dc72b0e4..850a1cbc 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs @@ -6,8 +6,8 @@ internal class AndroidLogcatPackageListItem : TreeViewItem { internal PackageEntry PackageEntry { get; } - internal AndroidLogcatPackageListItem(int depth, PackageEntry entry) - : base(entry.GetId(), depth) + internal AndroidLogcatPackageListItem(PackageEntry entry) + : base(entry.GetId(), 0) { PackageEntry = entry; } diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta similarity index 83% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta rename to com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta index 9a109567..19d50bf8 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewItem.cs.meta +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e3e55ab3ff10b724a809adeb77a2af8d +guid: 8472d03b54ff98d4381b12dc87f94bdf MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs new file mode 100644 index 00000000..c275f485 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.IMGUI.Controls; +using UnityEngine; +using UnityEngine.Assertions; + +namespace Unity.Android.Logcat +{ + // Note: UI Toolkit MulticolumnListView is not available in 2020 + [Serializable] + internal class AndroidLogcatPackageListViewState where T : Enum + { + internal enum Columns + { + PackageName, + Installer, + UniqueIdentifier, + Operations + } + + [SerializeField] + internal TreeViewState treeViewState; + + [SerializeField] + internal MultiColumnHeaderState columnHeaderState; + + [NonSerialized] + internal MultiColumnHeader columnHeader; + + internal static AndroidLogcatPackageListViewState CreateOrInitializeViewState(AndroidLogcatPackageListViewState state = null) + { + if (state == null) + state = new AndroidLogcatPackageListViewState(); + + if (state.treeViewState == null) + state.treeViewState = new TreeViewState(); + + bool firstInit = state.columnHeaderState == null; + var headerState = CreateMultiColumnHeaderState(); + if (MultiColumnHeaderState.CanOverwriteSerializedFields(state.columnHeaderState, headerState)) + MultiColumnHeaderState.OverwriteSerializedFields(state.columnHeaderState, headerState); + state.columnHeaderState = headerState; + + state.columnHeader = new MultiColumnHeader(headerState); + if (firstInit) + state.columnHeader.ResizeToFit(); + + return state; + } + + protected static MultiColumnHeaderState.Column CreateColumn(string name, float width) + { + return new MultiColumnHeaderState.Column + { + headerContent = new GUIContent(name), + headerTextAlignment = TextAlignment.Left, + canSort = false, + width = width, + minWidth = width, + autoResize = true, + allowToggleVisibility = false + }; + } + + private static MultiColumnHeaderState CreateMultiColumnHeaderState() + { + var columns = new[] + { + CreateColumn("Package Name", 250), + CreateColumn("Installer", 200), + CreateColumn("UID", 50), + CreateColumn("Operations", 50) + }; + Assert.AreEqual(columns.Length, Enum.GetValues(typeof(T)).Length, "Number of columns should match number of enum values: You probably forgot to update one of them."); + + return new MultiColumnHeaderState(columns); + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta similarity index 83% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta rename to com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta index d49fbfc7..0e6987bb 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs.meta +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e3ce8489378c95c42984e319a8b859ad +guid: f78887ddb339d9048838dc1dcea72c83 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs deleted file mode 100644 index 6ef1cdf7..00000000 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListViewState.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.Assertions; - -namespace Unity.Android.Logcat -{ - // Note: UI Toolkit MulticolumnListView is not available in 2020 - [Serializable] - internal class AndroidLogcatPackageListViewState - { - internal enum Columns - { - PackageName, - Installer, - UniqueIdentifier, - Operations - } - - [SerializeField] - internal TreeViewState treeViewState; - - [SerializeField] - internal MultiColumnHeaderState columnHeaderState; - - [NonSerialized] - internal MultiColumnHeader columnHeader; - - internal static AndroidLogcatPackageListViewState CreateOrInitializeTreeState(AndroidLogcatPackageListViewState state = null) - { - if (state == null) - state = new AndroidLogcatPackageListViewState(); - - if (state.treeViewState == null) - state.treeViewState = new TreeViewState(); - - bool firstInit = state.columnHeaderState == null; - var headerState = CreateMultiColumnHeaderState(); - if (MultiColumnHeaderState.CanOverwriteSerializedFields(state.columnHeaderState, headerState)) - MultiColumnHeaderState.OverwriteSerializedFields(state.columnHeaderState, headerState); - state.columnHeaderState = headerState; - - state.columnHeader = new MultiColumnHeader(headerState); - if (firstInit) - state.columnHeader.ResizeToFit(); - - return state; - } - - private static MultiColumnHeaderState CreateMultiColumnHeaderState() - { - var columns = new[] - { - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Package Name"), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = 250, - minWidth = 200, - autoResize = true, - allowToggleVisibility = false - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Installer", "The installer application"), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = 200, - minWidth = 200, - autoResize = true, - allowToggleVisibility = false - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("UID", "Unique Identifier"), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = 50, - minWidth = 50, - autoResize = true, - allowToggleVisibility = false - }, - new MultiColumnHeaderState.Column - { - headerContent = new GUIContent("Operations"), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = 200, - minWidth = 100, - autoResize = true, - allowToggleVisibility = false - } - }; - - Assert.AreEqual(columns.Length, Enum.GetValues(typeof(Columns)).Length, "Number of columns should match number of enum values: You probably forgot to update one of them."); - - var header = new MultiColumnHeaderState(columns); - return header; - } - } -} From 159f01417275f4cf3d89013c6faddb0211e8b91b Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Fri, 18 Nov 2022 21:16:04 +0200 Subject: [PATCH 07/43] update --- .../Editor/AndroidLogcatPackagesWindow.cs | 2 +- .../Editor/UI/AndroidLogcatPackageListView.cs | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 38671123..ea7842a3 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -21,7 +21,7 @@ static void Init() private void OnEnable() { - m_State = AndroidLogcatPackageListViewState.CreateOrInitializeTreeState(m_State); + m_State = AndroidLogcatPackageListViewState.CreateOrInitializeViewState(m_State); m_View = new AndroidLogcatPackageListView(m_State, GetPackageEntries()); } diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs index b2efa175..fe70edce 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs @@ -9,13 +9,8 @@ namespace Unity.Android.Logcat // Note: UI Toolkit MulticolumnListView is not available in 2020 internal class AndroidLogcatPackageListView : TreeView { - internal static class Styles - { - internal static GUIStyle buildSettingsButton = new GUIStyle(EditorStyles.miniButton) { alignment = TextAnchor.MiddleLeft }; - } - - private Dictionary m_CachedRowMap = new Dictionary(); public IReadOnlyList m_Entries; + public bool RequiresUpdating { set; get; } public AndroidLogcatPackageListView(AndroidLogcatPackageListViewState state, IReadOnlyList entries) @@ -38,11 +33,10 @@ protected override TreeViewItem BuildRoot() protected override IList BuildRows(TreeViewItem root) { - Debug.Log("Build Rows"); var items = new List(); foreach (var e in m_Entries) { - items.Add(new AndroidLogcatPackageListItem(0, e)); + items.Add(new AndroidLogcatPackageListItem(e)); } return items; From 2201271acb526306b0c1032cd689a2dc72432205 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 11 Feb 2023 00:11:29 +0200 Subject: [PATCH 08/43] Use uitoolkit --- .../Editor/AndroidLogcatPackagesWindow.cs | 144 ++++++++++++------ .../Editor/UI/AndroidLogcatListViewItem.cs | 17 --- .../UI/AndroidLogcatListViewItem.cs.meta | 11 -- .../Editor/UI/AndroidLogcatListViewState.cs | 80 ---------- .../UI/AndroidLogcatListViewState.cs.meta | 11 -- .../Editor/UI/AndroidLogcatPackageLabel.cs | 19 +++ ...meta => AndroidLogcatPackageLabel.cs.meta} | 2 +- .../Editor/UI/AndroidLogcatPackageListView.cs | 123 --------------- .../Editor/UI/Layouts.meta | 8 + .../Layouts/AndroidLogcatPackagesLayout.uxml | 9 ++ .../AndroidLogcatPackagesLayout.uxml.meta | 10 ++ 11 files changed, 142 insertions(+), 292 deletions(-) delete mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs delete mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta delete mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs delete mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs rename com.unity.mobile.android-logcat/Editor/UI/{AndroidLogcatPackageListView.cs.meta => AndroidLogcatPackageLabel.cs.meta} (83%) delete mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/Layouts.meta create mode 100644 com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml create mode 100644 com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml.meta diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index ea7842a3..3ac5ec08 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -1,49 +1,95 @@ -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; - -namespace Unity.Android.Logcat -{ - // adb shell cmd package list packages -3 -U -i - - internal class AndroidLogcatPackagesWindow : EditorWindow - { - AndroidLogcatPackageListView m_View; - AndroidLogcatPackageListViewState m_State; - [MenuItem("Window/My Window")] - static void Init() - { - // Get existing open window or if none, make a new one: - AndroidLogcatPackagesWindow window = (AndroidLogcatPackagesWindow)EditorWindow.GetWindow(typeof(AndroidLogcatPackagesWindow)); - window.Show(); - } - - private void OnEnable() - { - m_State = AndroidLogcatPackageListViewState.CreateOrInitializeViewState(m_State); - m_View = new AndroidLogcatPackageListView(m_State, GetPackageEntries()); - } - - PackageEntry[] GetPackageEntries() - { - return AndroidLogcatUtilities.RetrievePackages( - AndroidLogcatManager.instance.Runtime.Tools.ADB, - AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice); - } - - void OnGUI() - { - if (GUILayout.Button("Reload")) - m_View.Reload(GetPackageEntries()); - var rc = GUILayoutUtility.GetRect(new GUIContent(""), GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - if (m_View != null) - m_View.OnGUI(rc); - else - GUILayout.Label("Package View failed to create"); - - if (m_View.RequiresUpdating) - m_View.Reload(GetPackageEntries()); - } - } -} +using System; +using System.Linq; +using UnityEditor; +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + // adb shell cmd package list packages -3 -U -i + + internal class AndroidLogcatPackagesWindow : EditorWindow + { + MultiColumnListView m_ListView; + + [MenuItem("Test/Test")] + static void Init() + { + // Get existing open window or if none, make a new one: + AndroidLogcatPackagesWindow window = (AndroidLogcatPackagesWindow)EditorWindow.GetWindow(typeof(AndroidLogcatPackagesWindow)); + window.Show(); + } + + private void OnEnable() + { + var tree = AssetDatabase.LoadAssetAtPath("Packages/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml"); + tree.CloneTree(rootVisualElement); + + m_ListView = rootVisualElement.Q(); + + m_ListView.itemsSource = GetPackageEntries().ToList(); + CreateLabel(nameof(PackageEntry.Name), (e) => e.Name); + CreateLabel(nameof(PackageEntry.Installer), (e) => e.Installer); + CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); + } + + void CreateLabel(string name, Func getText, Func getTooltip = null) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => + { + var label = new PackageEntryLabel(); + label.RegisterCallback((e, l) => + { + switch (e.button) + { + case 0: + if (e.clickCount == 2) + { + //OnSelectEntryInListView(l.Entry); + } + break; + } + }, label); + return label; + }; + + m_ListView.columns[id].bindCell = (element, index) => + { + var label = GetInitializedElement(element, index); + label.text = getText(label.Entry); + if (getTooltip != null) + label.tooltip = getTooltip(label.Entry); + }; + } + + void CreateButton(string name) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => new PackageEntryButton(); + m_ListView.columns[id].bindCell = (element, index) => + { + var button = GetInitializedElement(element, index); + button.text = "Hello"; + }; + } + + T GetInitializedElement(VisualElement element, int index) where T : PackageEntryVisualElement + { + var packageEntryElement = (PackageEntryVisualElement)element; + packageEntryElement.Entry = (PackageEntry)m_ListView.itemsSource[index]; + return (T)packageEntryElement; + } + + PackageEntry[] GetPackageEntries() + { + return AndroidLogcatUtilities.RetrievePackages( + AndroidLogcatManager.instance.Runtime.Tools.ADB, + AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice); + } + + void OnGUI() + { + // GetPackageEntries(); + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs deleted file mode 100644 index 850a1cbc..00000000 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UnityEditor.IMGUI.Controls; - -namespace Unity.Android.Logcat -{ - internal class AndroidLogcatPackageListItem : TreeViewItem - { - internal PackageEntry PackageEntry { get; } - - internal AndroidLogcatPackageListItem(PackageEntry entry) - : base(entry.GetId(), 0) - { - PackageEntry = entry; - } - - public override bool hasChildren => false; - } -} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta deleted file mode 100644 index 19d50bf8..00000000 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewItem.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8472d03b54ff98d4381b12dc87f94bdf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs deleted file mode 100644 index c275f485..00000000 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.Assertions; - -namespace Unity.Android.Logcat -{ - // Note: UI Toolkit MulticolumnListView is not available in 2020 - [Serializable] - internal class AndroidLogcatPackageListViewState where T : Enum - { - internal enum Columns - { - PackageName, - Installer, - UniqueIdentifier, - Operations - } - - [SerializeField] - internal TreeViewState treeViewState; - - [SerializeField] - internal MultiColumnHeaderState columnHeaderState; - - [NonSerialized] - internal MultiColumnHeader columnHeader; - - internal static AndroidLogcatPackageListViewState CreateOrInitializeViewState(AndroidLogcatPackageListViewState state = null) - { - if (state == null) - state = new AndroidLogcatPackageListViewState(); - - if (state.treeViewState == null) - state.treeViewState = new TreeViewState(); - - bool firstInit = state.columnHeaderState == null; - var headerState = CreateMultiColumnHeaderState(); - if (MultiColumnHeaderState.CanOverwriteSerializedFields(state.columnHeaderState, headerState)) - MultiColumnHeaderState.OverwriteSerializedFields(state.columnHeaderState, headerState); - state.columnHeaderState = headerState; - - state.columnHeader = new MultiColumnHeader(headerState); - if (firstInit) - state.columnHeader.ResizeToFit(); - - return state; - } - - protected static MultiColumnHeaderState.Column CreateColumn(string name, float width) - { - return new MultiColumnHeaderState.Column - { - headerContent = new GUIContent(name), - headerTextAlignment = TextAlignment.Left, - canSort = false, - width = width, - minWidth = width, - autoResize = true, - allowToggleVisibility = false - }; - } - - private static MultiColumnHeaderState CreateMultiColumnHeaderState() - { - var columns = new[] - { - CreateColumn("Package Name", 250), - CreateColumn("Installer", 200), - CreateColumn("UID", 50), - CreateColumn("Operations", 50) - }; - Assert.AreEqual(columns.Length, Enum.GetValues(typeof(T)).Length, "Number of columns should match number of enum values: You probably forgot to update one of them."); - - return new MultiColumnHeaderState(columns); - } - } -} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta deleted file mode 100644 index 0e6987bb..00000000 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatListViewState.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f78887ddb339d9048838dc1dcea72c83 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs new file mode 100644 index 00000000..55ea832d --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs @@ -0,0 +1,19 @@ +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + interface PackageEntryVisualElement + { + PackageEntry Entry { set; get; } + } + + class PackageEntryLabel : Label, PackageEntryVisualElement + { + public PackageEntry Entry { set; get; } + } + + class PackageEntryButton : Button, PackageEntryVisualElement + { + public PackageEntry Entry { set; get; } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs.meta similarity index 83% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta rename to com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs.meta index 5e9b16df..6b395dd1 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs.meta +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 21dfae1ceb4c16745a6b9c172407e30c +guid: 41599afae27dd384b9ba08befb533c17 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs deleted file mode 100644 index fe70edce..00000000 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageListView.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace Unity.Android.Logcat -{ - // Note: UI Toolkit MulticolumnListView is not available in 2020 - internal class AndroidLogcatPackageListView : TreeView - { - public IReadOnlyList m_Entries; - - public bool RequiresUpdating { set; get; } - - public AndroidLogcatPackageListView(AndroidLogcatPackageListViewState state, IReadOnlyList entries) - : base(state.treeViewState, state.columnHeader) - { - m_Entries = entries; - - rowHeight = 20f; - showAlternatingRowBackgrounds = true; - showBorder = true; - customFoldoutYOffset = (rowHeight - EditorGUIUtility.singleLineHeight) * 0.5f; - extraSpaceBeforeIconAndLabel = 18f; - Reload(); - } - - protected override TreeViewItem BuildRoot() - { - return new TreeViewItem(0, -1); - } - - protected override IList BuildRows(TreeViewItem root) - { - var items = new List(); - foreach (var e in m_Entries) - { - items.Add(new AndroidLogcatPackageListItem(e)); - } - return items; - - } - - protected override void RowGUI(RowGUIArgs args) - { - var item = (AndroidLogcatPackageListItem)args.item; - for (int i = 0; i < args.GetNumVisibleColumns(); ++i) - { - Rect rc = args.GetCellRect(i); - if (i == columnIndexForTreeFoldouts) - { - var indent = GetContentIndent(item); - rc.x += indent; - rc.width -= indent; - } - DisplayItem(item, i, rc); - } - } - - private void DisplayItem(AndroidLogcatPackageListItem item, int c, Rect rc) - { - AndroidLogcatPackageListViewState.Columns column = (AndroidLogcatPackageListViewState.Columns)c; - - var props = item.PackageEntry; - EditorGUI.BeginChangeCheck(); - switch (column) - { - case AndroidLogcatPackageListViewState.Columns.PackageName: - GUI.Label(rc, new GUIContent(props.Name, props.Name)); - break; - case AndroidLogcatPackageListViewState.Columns.UniqueIdentifier: - GUI.Label(rc, new GUIContent(props.UID)); - break; - case AndroidLogcatPackageListViewState.Columns.Installer: - GUI.Label(rc, new GUIContent(props.Installer)); - break; - case AndroidLogcatPackageListViewState.Columns.Operations: - var rcSplit = new Rect(rc.x, rc.y, rc.width * 0.25f, rc.height); - if (GUI.Button(rcSplit, new GUIContent("Launch"))) - props.Launch(); - rcSplit.x += rcSplit.width; - if (GUI.Button(rcSplit, new GUIContent("Pause"))) - props.Pause(); - rcSplit.x += rcSplit.width; - if (GUI.Button(rcSplit, new GUIContent("Stop"))) - props.Stop(); - rcSplit.x += rcSplit.width; - if (GUI.Button(rcSplit, new GUIContent("Uninstall"))) - { - // TODO: Dialog asking are you sure - props.Uninstall(); - RequiresUpdating = true; - } - - break; - - /* - case AndroidLogcatPackageListViewState.Columns.Permissions: - GUI.Label(rc, props.Permissions); - //props.Build = EditorGUI.Toggle(rc, props.Build); - break; - case AndroidLogcatPackageListViewState.Columns.Date: - GUI.Label(rc, props.DateModified.ToString("yyyy-MM-dd HH:mm:ss")); - break; - case AndroidLogcatPackageListViewState.Columns.Size: - GUI.Label(rc, $"{props.Size.ToString()}B"); - break; - */ - } - - if (EditorGUI.EndChangeCheck()) - this.SetSelection(new List(new[] { props.GetId() }), TreeViewSelectionOptions.None); - } - - public void Reload(IReadOnlyList entries) - { - m_Entries = entries; - Reload(); - RequiresUpdating = false; - } - } -} diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts.meta b/com.unity.mobile.android-logcat/Editor/UI/Layouts.meta new file mode 100644 index 00000000..47460638 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2c3fe81b3bb81c04aac4dbc4cad17f37 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml new file mode 100644 index 00000000..d7771f64 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml.meta b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml.meta new file mode 100644 index 00000000..e8237fc7 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 6a0b5f795cb97794cb65533a587e917f +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} From 83f9bbf524e781296837f047dc1b04c3cbea60cc Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 11 Feb 2023 19:10:28 +0200 Subject: [PATCH 09/43] Add filter --- .../Editor/AndroidLogcatPackagesWindow.cs | 276 ++++++++++++------ .../Editor/UI/AndroidLogcatPackageLabel.cs | 10 +- .../Layouts/AndroidLogcatPackagesLayout.uxml | 19 +- .../Editor/AndroidLogcatPackageInfoTests.cs | 216 +++++++------- 4 files changed, 304 insertions(+), 217 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 3ac5ec08..fe0e6ad2 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -1,95 +1,181 @@ -using System; -using System.Linq; -using UnityEditor; -using UnityEngine.UIElements; - -namespace Unity.Android.Logcat -{ - // adb shell cmd package list packages -3 -U -i - - internal class AndroidLogcatPackagesWindow : EditorWindow - { - MultiColumnListView m_ListView; - - [MenuItem("Test/Test")] - static void Init() - { - // Get existing open window or if none, make a new one: - AndroidLogcatPackagesWindow window = (AndroidLogcatPackagesWindow)EditorWindow.GetWindow(typeof(AndroidLogcatPackagesWindow)); - window.Show(); - } - - private void OnEnable() - { - var tree = AssetDatabase.LoadAssetAtPath("Packages/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml"); - tree.CloneTree(rootVisualElement); - - m_ListView = rootVisualElement.Q(); - - m_ListView.itemsSource = GetPackageEntries().ToList(); - CreateLabel(nameof(PackageEntry.Name), (e) => e.Name); - CreateLabel(nameof(PackageEntry.Installer), (e) => e.Installer); - CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); - } - - void CreateLabel(string name, Func getText, Func getTooltip = null) - { - var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => - { - var label = new PackageEntryLabel(); - label.RegisterCallback((e, l) => - { - switch (e.button) - { - case 0: - if (e.clickCount == 2) - { - //OnSelectEntryInListView(l.Entry); - } - break; - } - }, label); - return label; - }; - - m_ListView.columns[id].bindCell = (element, index) => - { - var label = GetInitializedElement(element, index); - label.text = getText(label.Entry); - if (getTooltip != null) - label.tooltip = getTooltip(label.Entry); - }; - } - - void CreateButton(string name) - { - var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => new PackageEntryButton(); - m_ListView.columns[id].bindCell = (element, index) => - { - var button = GetInitializedElement(element, index); - button.text = "Hello"; - }; - } - - T GetInitializedElement(VisualElement element, int index) where T : PackageEntryVisualElement - { - var packageEntryElement = (PackageEntryVisualElement)element; - packageEntryElement.Entry = (PackageEntry)m_ListView.itemsSource[index]; - return (T)packageEntryElement; - } - - PackageEntry[] GetPackageEntries() - { - return AndroidLogcatUtilities.RetrievePackages( - AndroidLogcatManager.instance.Runtime.Tools.ADB, - AndroidLogcatManager.instance.Runtime.DeviceQuery.SelectedDevice); - } - - void OnGUI() - { - // GetPackageEntries(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + // adb shell dumpsys package + + // adb shell cmd package list packages + // list packages[-f] [-d] + // [-e] + // [-s] + // [-3] + // [-i] + // [-l] + // [-u] + // [-U] + // [--uid UID] + // [--user USER_ID] + // [FILTER] + // Prints all packages; optionally only those whose name contains the text in FILTER. + // Options: + // -f: see their associated file + // -d: filter to only show disabled packages + // -e: filter to only show enabled packages + // -s: filter to only show system packages + // -3: filter to only show third party packages + // -i: see the installer for the packages + // -l: ignored(used for compatibility with older releases) + // -U: also show the package UID + // -u: also include uninstalled packages + // --uid UID: filter to only show packages with the given UID + // --user USER_ID: only list packages belonging to the given user + + // Example., adb shell cmd package list packages -3 -U -i + + internal class AndroidLogcatPackagesWindow : EditorWindow + { + MultiColumnListView m_ListView; + AndroidLogcatRuntimeBase m_Runtime; + TextField m_Filter; + + List m_UnfilteredEntries; + List m_FilteredEntries; + + [MenuItem("Test/Test")] + static void Init() + { + // Get existing open window or if none, make a new one: + AndroidLogcatPackagesWindow window = (AndroidLogcatPackagesWindow)EditorWindow.GetWindow(typeof(AndroidLogcatPackagesWindow)); + window.titleContent = new UnityEngine.GUIContent("Packages"); + window.Show(); + } + + private void OnEnable() + { + m_Runtime = AndroidLogcatManager.instance.Runtime; + m_Runtime.DeviceQuery.DevicesUpdated += UpdateEntries; + + // No device selected yet + m_FilteredEntries = new List(); + m_UnfilteredEntries = new List(); + + var tree = AssetDatabase.LoadAssetAtPath("Packages/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml"); + tree.CloneTree(rootVisualElement); + + m_ListView = rootVisualElement.Q(); + m_Filter = rootVisualElement.Q("filter"); + // TODO: take filter from settings + m_Filter.RegisterValueChangedCallback((s) => + { + FilterBy(s.newValue); + }); + + m_ListView.itemsSource = m_UnfilteredEntries; + CreateLabel(nameof(PackageEntry.Name), (e) => e.Name); + CreateLabel(nameof(PackageEntry.Installer), (e) => e.Installer); + CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); + + rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); + } + + private void FilterBy(string filter) + { + m_FilteredEntries.Clear(); + if (string.IsNullOrEmpty(filter)) + { + m_FilteredEntries.AddRange(m_UnfilteredEntries); + } + else + { + foreach (var e in m_UnfilteredEntries) + { + if (e.Name.Contains(filter) || + e.Installer.Contains(filter) || + e.UID.Contains(filter)) + m_FilteredEntries.Add(e); + } + } + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + + private void UpdateEntries() + { + m_UnfilteredEntries = GetPackageEntries().ToList(); + FilterBy(m_Filter.value); + } + + void CreateLabel(string name, Func getText, Func getTooltip = null) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => + { + var label = new PackageEntryLabel(); + label.RegisterCallback((e, l) => + { + switch (e.button) + { + case 0: + if (e.clickCount == 2) + { + //OnSelectEntryInListView(l.Entry); + } + break; + } + }, label); + return label; + }; + + m_ListView.columns[id].bindCell = (element, index) => + { + var label = GetInitializedElement(element, index); + label.text = getText(label.Entry); + if (getTooltip != null) + label.tooltip = getTooltip(label.Entry); + }; + } + + void CreateButton(string name) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => new PackageEntryButton(); + m_ListView.columns[id].bindCell = (element, index) => + { + var button = GetInitializedElement(element, index); + button.text = "Hello"; + }; + } + + T GetInitializedElement(VisualElement element, int index) where T : PackageEntryVisualElement + { + var packageEntryElement = (PackageEntryVisualElement)element; + packageEntryElement.Entry = (PackageEntry)m_ListView.itemsSource[index]; + return (T)packageEntryElement; + } + + PackageEntry[] GetPackageEntries() + { + return AndroidLogcatUtilities.RetrievePackages( + m_Runtime.Tools.ADB, + m_Runtime.DeviceQuery.FirstConnectedDevice); + } + + void DoDebuggingGUI() + { + GUILayout.Label("Developer Mode is on, showing debugging buttons:", EditorStyles.boldLabel); + EditorGUILayout.BeginHorizontal(AndroidLogcatStyles.toolbar); + + if (GUILayout.Button("Reload Me", AndroidLogcatStyles.toolbarButton)) + { + EditorUtility.RequestScriptReload(); + } + EditorGUILayout.EndHorizontal(); + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs index 55ea832d..4dffd0a7 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs @@ -2,16 +2,16 @@ namespace Unity.Android.Logcat { - interface PackageEntryVisualElement - { - PackageEntry Entry { set; get; } + interface PackageEntryVisualElement + { + PackageEntry Entry { set; get; } } class PackageEntryLabel : Label, PackageEntryVisualElement { public PackageEntry Entry { set; get; } - } - + } + class PackageEntryButton : Button, PackageEntryVisualElement { public PackageEntry Entry { set; get; } diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index d7771f64..816495ff 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -1,9 +1,10 @@ - - - - - - - - - + + + + + + + + + + diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs index e6a4128d..60e39c49 100644 --- a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs @@ -2,112 +2,112 @@ using NUnit.Framework; using System.Text.RegularExpressions; using Unity.Android.Logcat; -using System.Linq; -using System.Text; - -class AndroidLogcatPacakgeInfoTests -{ - [Test] - public void CanParsePackageInfo() - { - var contents = @" Package [com.DefaultCompany.AndroidEmptyGameActivity] (ffc5f27): - userId=10198 - pkg=Package{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} - codePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== - resourcePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== - legacyNativeLibraryDir=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ==/lib - primaryCpuAbi=armeabi-v7a - secondaryCpuAbi=null - versionCode=1 minSdk=22 targetSdk=32 - versionName=0.1 - splits=[base] - apkSigningVersion=2 - applicationInfo=ApplicationInfo{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} - flags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] - privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ] - forceQueryable=false - queriesPackages=[] - dataDir=/data/user/0/com.DefaultCompany.AndroidEmptyGameActivity - supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity] - timeStamp=2022-09-19 15:52:25 - firstInstallTime=2022-09-13 16:14:57 - lastUpdateTime=2022-09-19 15:52:26 - signatures=PackageSignatures{af06a3b version:2, signatures:[ca97cd1f], past signatures:[]} - installPermissionsFixed=true - pkgFlags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] - requested permissions: - android.permission.INTERNET - android.permission.ACCESS_NETWORK_STATE - install permissions: - android.permission.INTERNET: granted=true - android.permission.ACCESS_NETWORK_STATE: granted=true - User 0: ceDataInode=311793 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false - gids=[3003] - runtime permissions: -"; - - var errors = new StringBuilder(); - var lines = contents.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries).Select(s => s.TrimStart()).ToArray(); - - if (lines.Length == 0) - throw new System.Exception("No package info found"); - var packageName = Regex.Escape("com.DefaultCompany.AndroidEmptyGameActivity"); - var title = new Regex($"Package.*{packageName}.*\\:"); - - if (!title.Match(lines[0]).Success) - throw new System.Exception($"Expected 'Package [] () :', but got '{lines[0]}'"); - - var keyValueRegex = new Regex(@"(?\S+)\=(?.*)"); - for (int i = 1; i < lines.Length; i++) - { - var l = lines[i]; - // Check if next lines are list - while (l.EndsWith("permissions:")) - { - UnityEngine.Debug.Log($"{l}"); - i++; - // List permissions - while (i < lines.Length) - { - var entry = lines[i]; - if (entry.StartsWith("android.permission")) - { - UnityEngine.Debug.Log($"P--> {entry}"); - i++; - } - else - { - l = lines[i]; - break; - } - } - - if (i >= lines.Length) - break; - } - - if (i >= lines.Length) - break; - - var result = keyValueRegex.Match(l); - - if (result.Success) - { - var key = result.Groups["key"]; - var value = result.Groups["value"]; - - UnityEngine.Debug.Log($"{key}={value}"); - continue; - } - - - errors.AppendLine($"Failed to resolve {l}"); - } - - if (errors.Length > 0) - { - UnityEngine.Debug.LogError($"Found errors:\n{errors.ToString()}\n\nin\n{contents}"); - } - - } +using System.Linq; +using System.Text; + +class AndroidLogcatPacakgeInfoTests +{ + [Test] + public void CanParsePackageInfo() + { + var contents = @" Package [com.DefaultCompany.AndroidEmptyGameActivity] (ffc5f27): + userId=10198 + pkg=Package{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} + codePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== + resourcePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== + legacyNativeLibraryDir=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ==/lib + primaryCpuAbi=armeabi-v7a + secondaryCpuAbi=null + versionCode=1 minSdk=22 targetSdk=32 + versionName=0.1 + splits=[base] + apkSigningVersion=2 + applicationInfo=ApplicationInfo{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} + flags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] + privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ] + forceQueryable=false + queriesPackages=[] + dataDir=/data/user/0/com.DefaultCompany.AndroidEmptyGameActivity + supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity] + timeStamp=2022-09-19 15:52:25 + firstInstallTime=2022-09-13 16:14:57 + lastUpdateTime=2022-09-19 15:52:26 + signatures=PackageSignatures{af06a3b version:2, signatures:[ca97cd1f], past signatures:[]} + installPermissionsFixed=true + pkgFlags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] + requested permissions: + android.permission.INTERNET + android.permission.ACCESS_NETWORK_STATE + install permissions: + android.permission.INTERNET: granted=true + android.permission.ACCESS_NETWORK_STATE: granted=true + User 0: ceDataInode=311793 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false + gids=[3003] + runtime permissions: +"; + + var errors = new StringBuilder(); + var lines = contents.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries).Select(s => s.TrimStart()).ToArray(); + + if (lines.Length == 0) + throw new System.Exception("No package info found"); + var packageName = Regex.Escape("com.DefaultCompany.AndroidEmptyGameActivity"); + var title = new Regex($"Package.*{packageName}.*\\:"); + + if (!title.Match(lines[0]).Success) + throw new System.Exception($"Expected 'Package [] () :', but got '{lines[0]}'"); + + var keyValueRegex = new Regex(@"(?\S+)\=(?.*)"); + for (int i = 1; i < lines.Length; i++) + { + var l = lines[i]; + // Check if next lines are list + while (l.EndsWith("permissions:")) + { + UnityEngine.Debug.Log($"{l}"); + i++; + // List permissions + while (i < lines.Length) + { + var entry = lines[i]; + if (entry.StartsWith("android.permission")) + { + UnityEngine.Debug.Log($"P--> {entry}"); + i++; + } + else + { + l = lines[i]; + break; + } + } + + if (i >= lines.Length) + break; + } + + if (i >= lines.Length) + break; + + var result = keyValueRegex.Match(l); + + if (result.Success) + { + var key = result.Groups["key"]; + var value = result.Groups["value"]; + + UnityEngine.Debug.Log($"{key}={value}"); + continue; + } + + + errors.AppendLine($"Failed to resolve {l}"); + } + + if (errors.Length > 0) + { + UnityEngine.Debug.LogError($"Found errors:\n{errors.ToString()}\n\nin\n{contents}"); + } + + } } From b1891423af02e6b94dc6f7eceeea9f1bd131c643 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 11 Feb 2023 19:31:02 +0200 Subject: [PATCH 10/43] sorting enabled --- .../Editor/AndroidLogcatPackagesWindow.cs | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index fe0e6ad2..9fc58a57 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -76,13 +76,43 @@ private void OnEnable() }); m_ListView.itemsSource = m_UnfilteredEntries; + m_ListView.sortingEnabled = true; + m_ListView.columnSortingChanged += ColumnSortingChanged; CreateLabel(nameof(PackageEntry.Name), (e) => e.Name); CreateLabel(nameof(PackageEntry.Installer), (e) => e.Installer); CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); - } - + } + + private void ColumnSortingChanged() + { + var column = m_ListView.sortedColumns.FirstOrDefault(); + m_FilteredEntries.Sort((x, y) => + { + var result = 0; + if (column.columnName.Equals(nameof(PackageEntry.Name), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.Name.CompareTo(y.Name); + } + else if (column.columnName.Equals(nameof(PackageEntry.Installer), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.Installer.CompareTo(y.Installer); + } + else if (column.columnName.Equals(nameof(PackageEntry.UID), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.UID.CompareTo(y.UID); + } + + if (column.direction == SortDirection.Descending) + return result; + return -result; + }); + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + private void FilterBy(string filter) { m_FilteredEntries.Clear(); From a6d4c2f2e7370780a376dca314753756b08dc6a7 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 11 Feb 2023 23:59:54 +0200 Subject: [PATCH 11/43] Doing package info --- .../Editor/AndroidLogcatPacakgeInfoParser.cs | 66 +++++++++++++++++++ .../AndroidLogcatPacakgeInfoParser.cs.meta | 11 ++++ .../Editor/AndroidLogcatPackagesWindow.cs | 9 +++ .../Layouts/AndroidLogcatPackagesLayout.uxml | 37 ++++++++--- .../Editor/AndroidLogcatPackageInfoTests.cs | 23 ++++--- 5 files changed, 126 insertions(+), 20 deletions(-) create mode 100644 com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs create mode 100644 com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs new file mode 100644 index 00000000..36dca127 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs @@ -0,0 +1,66 @@ +using System; +using System.Linq; +using System.IO; +using System.Text.RegularExpressions; +using UnityEngine; +using System.Collections.Generic; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackageInfoParser + { + // Note: Using List instead of Dictionary in case of duplicate keys + List> m_Entries; + + IReadOnlyList> Entries => m_Entries; + + internal AndroidLogcatPackageInfoParser(string contents, string packageName) + { + m_Entries = new List>(); + + var lines = contents.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries).ToArray(); + + if (lines.Length == 0) + throw new System.Exception("No package info found"); + var regexPackageName = Regex.Escape(packageName); + var title = new Regex($"Package.*{regexPackageName}.*\\:"); + + if (!title.Match(lines[0]).Success) + throw new Exception($"Expected 'Package [{packageName}] () :', but got '{lines[0]}'"); + + var keyValueRegex = new Regex(@"\s+(?\S+[^\=])\=(?[^\=]\S+)"); + for (int i = 1; i < lines.Length; i++) + { + var l = lines[i]; + + // Is it a permissions block + if (l.EndsWith("permissions:")) + { + var key = l.Trim(); + var value = string.Empty; + m_Entries.Add(new KeyValuePair(key, value)); + } + else + { + var result = keyValueRegex.Match(l); + + if (result.Success) + { + var key = result.Groups["key"].Value; + var value = result.Groups["value"].Value; + + m_Entries.Add(new KeyValuePair(key, value)); + } + else + { + // Keep failures too + m_Entries.Add(new KeyValuePair("Failed", l)); + } + } + + } + + } + + } +} diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs.meta b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs.meta new file mode 100644 index 00000000..c1ed77b0 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 146dcd6dccd16e9488544d6f58f9b1a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 9fc58a57..83b085ab 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -67,6 +67,8 @@ private void OnEnable() var tree = AssetDatabase.LoadAssetAtPath("Packages/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml"); tree.CloneTree(rootVisualElement); + rootVisualElement.Q().RegisterCallback(InitializeLayout); + m_ListView = rootVisualElement.Q(); m_Filter = rootVisualElement.Q("filter"); // TODO: take filter from settings @@ -85,6 +87,13 @@ private void OnEnable() rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); } + internal void InitializeLayout(GeometryChangedEvent e) + { + var split = rootVisualElement.Q(); + split.fixedPaneInitialDimension = split.layout.width / 2; + split.UnregisterCallback(InitializeLayout); + } + private void ColumnSortingChanged() { var column = m_ListView.sortedColumns.FirstOrDefault(); diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index 816495ff..1f01a8c3 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -1,10 +1,27 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs index 60e39c49..6bc41f06 100644 --- a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs @@ -7,32 +7,34 @@ class AndroidLogcatPacakgeInfoTests { + // adb shell dumpsys package [Test] public void CanParsePackageInfo() { - var contents = @" Package [com.DefaultCompany.AndroidEmptyGameActivity] (ffc5f27): + var packageName = "com.DefaultCompany.AndroidEmptyGameActivity"; + var contents = @$" Package [{packageName}] (ffc5f27): userId=10198 - pkg=Package{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} - codePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== - resourcePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ== - legacyNativeLibraryDir=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/com.DefaultCompany.AndroidEmptyGameActivity-bzIOds7vr6jRoCaEw1TacQ==/lib + pkg=Package{{d78b8ca {packageName}}} + codePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/{packageName}-bzIOds7vr6jRoCaEw1TacQ== + resourcePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/{packageName}-bzIOds7vr6jRoCaEw1TacQ== + legacyNativeLibraryDir=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/{packageName}-bzIOds7vr6jRoCaEw1TacQ==/lib primaryCpuAbi=armeabi-v7a secondaryCpuAbi=null versionCode=1 minSdk=22 targetSdk=32 versionName=0.1 splits=[base] apkSigningVersion=2 - applicationInfo=ApplicationInfo{d78b8ca com.DefaultCompany.AndroidEmptyGameActivity} + applicationInfo=ApplicationInfo{{d78b8ca {packageName}}} flags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ] forceQueryable=false queriesPackages=[] - dataDir=/data/user/0/com.DefaultCompany.AndroidEmptyGameActivity + dataDir=/data/user/0/{packageName} supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity] timeStamp=2022-09-19 15:52:25 firstInstallTime=2022-09-13 16:14:57 lastUpdateTime=2022-09-19 15:52:26 - signatures=PackageSignatures{af06a3b version:2, signatures:[ca97cd1f], past signatures:[]} + signatures=PackageSignatures{{af06a3b version:2, signatures:[ca97cd1f], past signatures:[]}} installPermissionsFixed=true pkgFlags=[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ] requested permissions: @@ -51,8 +53,8 @@ public void CanParsePackageInfo() if (lines.Length == 0) throw new System.Exception("No package info found"); - var packageName = Regex.Escape("com.DefaultCompany.AndroidEmptyGameActivity"); - var title = new Regex($"Package.*{packageName}.*\\:"); + var regexPackageName = Regex.Escape(packageName); + var title = new Regex($"Package.*{regexPackageName}.*\\:"); if (!title.Match(lines[0]).Success) throw new System.Exception($"Expected 'Package [] () :', but got '{lines[0]}'"); @@ -61,6 +63,7 @@ public void CanParsePackageInfo() for (int i = 1; i < lines.Length; i++) { var l = lines[i]; + // Check if next lines are list while (l.EndsWith("permissions:")) { From e8c89d2c487b90133339449181892f4fb14648d5 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sun, 12 Feb 2023 18:27:02 +0200 Subject: [PATCH 12/43] Working on parser --- .../Editor/AndroidLogcatPacakgeInfoParser.cs | 204 +++++++++++++----- .../Editor/AndroidLogcatPackagesWindow.cs | 62 +++--- .../Layouts/AndroidLogcatPackagesLayout.uxml | 54 ++--- .../Editor/AndroidLogcatPackageInfoTests.cs | 172 +++++++++------ 4 files changed, 317 insertions(+), 175 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs index 36dca127..415dcf31 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs @@ -1,66 +1,156 @@ using System; using System.Linq; -using System.IO; using System.Text.RegularExpressions; -using UnityEngine; using System.Collections.Generic; +using System.Text; namespace Unity.Android.Logcat { - internal class AndroidLogcatPackageInfoParser - { - // Note: Using List instead of Dictionary in case of duplicate keys - List> m_Entries; - - IReadOnlyList> Entries => m_Entries; - - internal AndroidLogcatPackageInfoParser(string contents, string packageName) - { - m_Entries = new List>(); - - var lines = contents.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries).ToArray(); - - if (lines.Length == 0) - throw new System.Exception("No package info found"); - var regexPackageName = Regex.Escape(packageName); - var title = new Regex($"Package.*{regexPackageName}.*\\:"); - - if (!title.Match(lines[0]).Success) - throw new Exception($"Expected 'Package [{packageName}] () :', but got '{lines[0]}'"); - - var keyValueRegex = new Regex(@"\s+(?\S+[^\=])\=(?[^\=]\S+)"); - for (int i = 1; i < lines.Length; i++) - { - var l = lines[i]; - - // Is it a permissions block - if (l.EndsWith("permissions:")) - { - var key = l.Trim(); - var value = string.Empty; - m_Entries.Add(new KeyValuePair(key, value)); - } - else - { - var result = keyValueRegex.Match(l); - - if (result.Success) - { - var key = result.Groups["key"].Value; - var value = result.Groups["value"].Value; - - m_Entries.Add(new KeyValuePair(key, value)); - } - else - { - // Keep failures too - m_Entries.Add(new KeyValuePair("Failed", l)); - } - } - - } - - } - + internal class AndroidLogcatPackageInfoParser + { + internal static readonly string FailedKey = "Failed"; + // Note: Using List instead of Dictionary in case of duplicate keys + List> m_Entries; + + internal IReadOnlyList> Entries => m_Entries; + + internal AndroidLogcatPackageInfoParser(string contents, string packageName) + { + m_Entries = new List>(); + + contents = contents.Replace("\r\n", "\n"); + + // Note: Keep empty entries, helps us to determine block end + var lines = contents.Split(new[] { '\n' }).ToArray(); + for (int i = 0; i < lines.Length; i++) + { + // Find block start + if (!lines[i].Trim().StartsWith($"Package [{packageName}]")) + continue; + + var blockStart = i; + var blockEnd = -1; + for (var l = blockStart + 1; l < lines.Length; l++) + { + blockEnd = l; + // Find block end + if (string.IsNullOrEmpty(lines[blockEnd].Trim())) + { + blockEnd--; + break; + } + } + + var length = blockEnd - blockStart + 1; + if (length <= 0) + return; + + var blockLines = lines.Skip(i).Take(length).ToArray(); + ParsePackageInformation(blockLines, packageName); + return; + } + } + + private void ParsePackageInformation(string[] lines, string packageName) + { + if (lines.Length == 0) + throw new System.Exception("No package info found"); + + var regexPackageName = Regex.Escape(packageName); + var title = new Regex($"Package.*{regexPackageName}.*\\:"); + + if (!title.Match(lines[0]).Success) + throw new Exception($"Expected 'Package [{packageName}] () :', but got '{lines[0]}'"); + + var keyValueRegex = new Regex(@"\s+(?\w+)\=(?.*)"); + for (var i = 1; i < lines.Length;) + { + var l = lines[i]; + + // Is it a permissions block? + if (l.EndsWith("permissions:")) + { + var key = l.Trim(); + var values = ParsePermissionBlock(lines, i, out var blockLength); + m_Entries.Add(new KeyValuePair(key, values)); + i += blockLength; + continue; + } + + // Normal entry + var result = keyValueRegex.Match(l); + + if (result.Success) + { + var key = result.Groups["key"].Value; + var value = result.Groups["value"] == null ? string.Empty : result.Groups["value"].Value; + + m_Entries.Add(new KeyValuePair(key, value)); + } + else + { + // Failed to parse value, add it as well for easier debugging + m_Entries.Add(new KeyValuePair(FailedKey, l)); + } + + i++; + } + } + + private int GetBlockEnd(string[] lines, int blockStart) + { + // Figure out block end + // For ex., + // requested permissions: + // android.permission.INTERNET + // android.permission.ACCESS_NETWORK_STATE + // if blockStart == 0, blockEnd will be 3 + var l = lines[blockStart]; + var indentation = l.TakeWhile(c => char.IsWhiteSpace(c)).Count(); + + var blockEnd = blockStart + 1; + while (blockEnd < lines.Length) + { + l = lines[blockEnd]; + var blockIndentation = l.TakeWhile(c => char.IsWhiteSpace(c)).Count(); + if (blockIndentation > indentation) + blockEnd++; + else + break; + } + + return blockEnd - 1; + } + + private string ParsePermissionBlock(string[] lines, int permissionsStart, out int blockLength) + { + blockLength = 1; + var value = string.Empty; + + if (permissionsStart + 1 >= lines.Length) + return string.Empty; + + var permissionsEnd = GetBlockEnd(lines, permissionsStart); + + // Collect values + for (int p = permissionsStart + 1; p <= permissionsEnd; p++) + { + if (value.Length > 0) + value += ", "; + value += lines[p].Trim(); + } + blockLength = permissionsEnd - permissionsStart + 1; + return value; + } + + internal string GetEntriesString() + { + var values = new StringBuilder(); + foreach (var e in Entries) + { + values.AppendLine($"{e.Key} = {e.Value}"); + } + return values.ToString(); + } } } diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 83b085ab..e530a429 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -85,43 +85,43 @@ private void OnEnable() CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); - } - + } + internal void InitializeLayout(GeometryChangedEvent e) { var split = rootVisualElement.Q(); split.fixedPaneInitialDimension = split.layout.width / 2; split.UnregisterCallback(InitializeLayout); - } - - private void ColumnSortingChanged() - { - var column = m_ListView.sortedColumns.FirstOrDefault(); - m_FilteredEntries.Sort((x, y) => - { - var result = 0; - if (column.columnName.Equals(nameof(PackageEntry.Name), StringComparison.InvariantCultureIgnoreCase)) - { - result = x.Name.CompareTo(y.Name); - } - else if (column.columnName.Equals(nameof(PackageEntry.Installer), StringComparison.InvariantCultureIgnoreCase)) - { - result = x.Installer.CompareTo(y.Installer); - } - else if (column.columnName.Equals(nameof(PackageEntry.UID), StringComparison.InvariantCultureIgnoreCase)) - { - result = x.UID.CompareTo(y.UID); - } - - if (column.direction == SortDirection.Descending) - return result; - return -result; - }); - + } + + private void ColumnSortingChanged() + { + var column = m_ListView.sortedColumns.FirstOrDefault(); + m_FilteredEntries.Sort((x, y) => + { + var result = 0; + if (column.columnName.Equals(nameof(PackageEntry.Name), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.Name.CompareTo(y.Name); + } + else if (column.columnName.Equals(nameof(PackageEntry.Installer), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.Installer.CompareTo(y.Installer); + } + else if (column.columnName.Equals(nameof(PackageEntry.UID), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.UID.CompareTo(y.UID); + } + + if (column.direction == SortDirection.Descending) + return result; + return -result; + }); + m_ListView.itemsSource = m_FilteredEntries; - m_ListView.RefreshItems(); - } - + m_ListView.RefreshItems(); + } + private void FilterBy(string filter) { m_FilteredEntries.Clear(); diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index 1f01a8c3..f2da9123 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -1,27 +1,27 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs index 6bc41f06..ac98b2b0 100644 --- a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs @@ -1,18 +1,55 @@ +using System; using System.Collections.Generic; using NUnit.Framework; using System.Text.RegularExpressions; using Unity.Android.Logcat; using System.Linq; using System.Text; +using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics; class AndroidLogcatPacakgeInfoTests { + private void AssertDictionary(Dictionary dictionary, string key, string value) + { + var allKeys = string.Join("\n", dictionary.Keys); + Assert.IsTrue(dictionary.ContainsKey(key), $"Key {key} doesn't exist, existing keys:\n{allKeys}"); + + Assert.IsTrue(dictionary[key].Equals(value), $"Key = {key}, expected value '{value}', but got '{dictionary[key]}'"); + } + + private Dictionary EntriesToDictionary(AndroidLogcatPackageInfoParser parser) + { + Assert.That(parser.Entries.Count, Is.GreaterThan(0)); + + var failedParsings = new StringBuilder(); + foreach (var e in parser.Entries) + { + if (e.Key.Equals(AndroidLogcatPackageInfoParser.FailedKey)) + failedParsings.AppendLine(e.Value); + } + + Assert.IsTrue(failedParsings.Length == 0, $"Failed to parse some values:\n{failedParsings}"); + + Dictionary entries; + try + { + entries = parser.Entries.ToDictionary(x => x.Key, x => x.Value); + } + catch (Exception ex) + { + throw new Exception($"Failed to form dictionary from:\n{parser.GetEntriesString()}", ex); + } + return entries; + } + // adb shell dumpsys package [Test] public void CanParsePackageInfo() { var packageName = "com.DefaultCompany.AndroidEmptyGameActivity"; - var contents = @$" Package [{packageName}] (ffc5f27): + var contents = @$" Some other data + + Package [{packageName}] (ffc5f27): userId=10198 pkg=Package{{d78b8ca {packageName}}} codePath=/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/{packageName}-bzIOds7vr6jRoCaEw1TacQ== @@ -30,6 +67,7 @@ public void CanParsePackageInfo() forceQueryable=false queriesPackages=[] dataDir=/data/user/0/{packageName} + fakeEmptyEntry= supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity] timeStamp=2022-09-19 15:52:25 firstInstallTime=2022-09-13 16:14:57 @@ -47,70 +85,84 @@ public void CanParsePackageInfo() gids=[3003] runtime permissions: "; + var parser = new AndroidLogcatPackageInfoParser(contents, packageName); + var entries = EntriesToDictionary(parser); + + AssertDictionary(entries, "pkg", $"Package{{d78b8ca {packageName}}}"); + AssertDictionary(entries, "codePath", $"/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/{packageName}-bzIOds7vr6jRoCaEw1TacQ=="); + AssertDictionary(entries, "flags", "[ DEBUGGABLE HAS_CODE ALLOW_CLEAR_USER_DATA TEST_ONLY ALLOW_BACKUP ]"); + AssertDictionary(entries, "firstInstallTime", $"2022-09-13 16:14:57"); + AssertDictionary(entries, "fakeEmptyEntry", string.Empty); + AssertDictionary(entries, "signatures", $"PackageSignatures{{af06a3b version:2, signatures:[ca97cd1f], past signatures:[]}}"); + } + + [Test] + public void CanParseEmpty() + { + var packageName = "com.dummy.dummy"; + var permissionsEndWithEndLine = @$" + Package [{packageName}] (ffc5f27):"; + var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithEndLine, packageName); + Assert.AreEqual(0, parser.Entries.Count); + } + + [Test] + public void CanParsePermissionsWithEndLine() + { + var packageName = "com.dummy.dummy"; + var permissionsEndWithEndLine = @$" + Package [{packageName}] (ffc5f27): + requested permissions: + android.permission.INTERNET + android.permission.ACCESS_NETWORK_STATE"; + + var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithEndLine, packageName); + var entries = EntriesToDictionary(parser); + + AssertDictionary(entries, "requested permissions:", $"android.permission.INTERNET, android.permission.ACCESS_NETWORK_STATE"); + } + + [Test] + public void CanParsePermissionsWithExtraLine() + { + var packageName = "com.dummy.dummy"; + var permissionsEndWithExtraLine = @$" + Package [{packageName}] (ffc5f27): + requested permissions: + android.permission.INTERNET + android.permission.ACCESS_NETWORK_STATE +"; + var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithExtraLine, packageName); + var entries = EntriesToDictionary(parser); - var errors = new StringBuilder(); - var lines = contents.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries).Select(s => s.TrimStart()).ToArray(); + AssertDictionary(entries, "requested permissions:", $"android.permission.INTERNET, android.permission.ACCESS_NETWORK_STATE"); + } - if (lines.Length == 0) - throw new System.Exception("No package info found"); - var regexPackageName = Regex.Escape(packageName); - var title = new Regex($"Package.*{regexPackageName}.*\\:"); + [Test] + public void CanParsePermissionsEmpty() + { + var packageName = "com.dummy.dummy"; + var permissionsEndWithExtraLine = @$" + Package [{packageName}] (ffc5f27): + requested permissions:"; - if (!title.Match(lines[0]).Success) - throw new System.Exception($"Expected 'Package [] () :', but got '{lines[0]}'"); + var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithExtraLine, packageName); + var entries = EntriesToDictionary(parser); - var keyValueRegex = new Regex(@"(?\S+)\=(?.*)"); - for (int i = 1; i < lines.Length; i++) - { - var l = lines[i]; - - // Check if next lines are list - while (l.EndsWith("permissions:")) - { - UnityEngine.Debug.Log($"{l}"); - i++; - // List permissions - while (i < lines.Length) - { - var entry = lines[i]; - if (entry.StartsWith("android.permission")) - { - UnityEngine.Debug.Log($"P--> {entry}"); - i++; - } - else - { - l = lines[i]; - break; - } - } - - if (i >= lines.Length) - break; - } - - if (i >= lines.Length) - break; - - var result = keyValueRegex.Match(l); - - if (result.Success) - { - var key = result.Groups["key"]; - var value = result.Groups["value"]; - - UnityEngine.Debug.Log($"{key}={value}"); - continue; - } - - - errors.AppendLine($"Failed to resolve {l}"); - } + AssertDictionary(entries, "requested permissions:", string.Empty); + } - if (errors.Length > 0) - { - UnityEngine.Debug.LogError($"Found errors:\n{errors.ToString()}\n\nin\n{contents}"); - } + [Test] + public void CanParsePermissionsEmptyWithExtraLine() + { + var packageName = "com.dummy.dummy"; + var permissionsEndWithExtraLine = @$" + Package [{packageName}] (ffc5f27): + requested permissions: +"; + var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithExtraLine, packageName); + var entries = EntriesToDictionary(parser); + AssertDictionary(entries, "requested permissions:", string.Empty); } } From 507731577c48f78ca6541edd4e0ccb2b0514cdca Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sun, 12 Feb 2023 18:39:58 +0200 Subject: [PATCH 13/43] Move code to AndroidLogcatPackages --- .../Editor/AndroidLogcatPackagesWindow.cs | 120 ++-------------- .../Editor/UI/AndroidLogcatPackages.cs | 132 ++++++++++++++++++ .../Editor/UI/AndroidLogcatPackages.cs.meta | 11 ++ 3 files changed, 156 insertions(+), 107 deletions(-) create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index e530a429..9dbdc09f 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -39,8 +39,9 @@ namespace Unity.Android.Logcat internal class AndroidLogcatPackagesWindow : EditorWindow { - MultiColumnListView m_ListView; AndroidLogcatRuntimeBase m_Runtime; + AndroidLogcatPackages m_Packages; + MultiColumnListView m_ListView; TextField m_Filter; List m_UnfilteredEntries; @@ -57,6 +58,9 @@ static void Init() private void OnEnable() { + if (rootVisualElement == null) + throw new NullReferenceException("rooVisualElement is null"); + m_Runtime = AndroidLogcatManager.instance.Runtime; m_Runtime.DeviceQuery.DevicesUpdated += UpdateEntries; @@ -69,117 +73,24 @@ private void OnEnable() rootVisualElement.Q().RegisterCallback(InitializeLayout); - m_ListView = rootVisualElement.Q(); - m_Filter = rootVisualElement.Q("filter"); - // TODO: take filter from settings - m_Filter.RegisterValueChangedCallback((s) => - { - FilterBy(s.newValue); - }); - - m_ListView.itemsSource = m_UnfilteredEntries; - m_ListView.sortingEnabled = true; - m_ListView.columnSortingChanged += ColumnSortingChanged; - CreateLabel(nameof(PackageEntry.Name), (e) => e.Name); - CreateLabel(nameof(PackageEntry.Installer), (e) => e.Installer); - CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); + m_Packages = new AndroidLogcatPackages(rootVisualElement, GetPackageEntries().ToList()); rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); } - internal void InitializeLayout(GeometryChangedEvent e) - { - var split = rootVisualElement.Q(); - split.fixedPaneInitialDimension = split.layout.width / 2; - split.UnregisterCallback(InitializeLayout); - } - - private void ColumnSortingChanged() - { - var column = m_ListView.sortedColumns.FirstOrDefault(); - m_FilteredEntries.Sort((x, y) => - { - var result = 0; - if (column.columnName.Equals(nameof(PackageEntry.Name), StringComparison.InvariantCultureIgnoreCase)) - { - result = x.Name.CompareTo(y.Name); - } - else if (column.columnName.Equals(nameof(PackageEntry.Installer), StringComparison.InvariantCultureIgnoreCase)) - { - result = x.Installer.CompareTo(y.Installer); - } - else if (column.columnName.Equals(nameof(PackageEntry.UID), StringComparison.InvariantCultureIgnoreCase)) - { - result = x.UID.CompareTo(y.UID); - } - - if (column.direction == SortDirection.Descending) - return result; - return -result; - }); - - m_ListView.itemsSource = m_FilteredEntries; - m_ListView.RefreshItems(); - } - - private void FilterBy(string filter) - { - m_FilteredEntries.Clear(); - if (string.IsNullOrEmpty(filter)) - { - m_FilteredEntries.AddRange(m_UnfilteredEntries); - } - else - { - foreach (var e in m_UnfilteredEntries) - { - if (e.Name.Contains(filter) || - e.Installer.Contains(filter) || - e.UID.Contains(filter)) - m_FilteredEntries.Add(e); - } - } - - m_ListView.itemsSource = m_FilteredEntries; - m_ListView.RefreshItems(); - } - private void UpdateEntries() { - m_UnfilteredEntries = GetPackageEntries().ToList(); - FilterBy(m_Filter.value); + m_Packages.RefreshEntries(GetPackageEntries().ToList()); } - void CreateLabel(string name, Func getText, Func getTooltip = null) + internal void InitializeLayout(GeometryChangedEvent e) { - var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => - { - var label = new PackageEntryLabel(); - label.RegisterCallback((e, l) => - { - switch (e.button) - { - case 0: - if (e.clickCount == 2) - { - //OnSelectEntryInListView(l.Entry); - } - break; - } - }, label); - return label; - }; - - m_ListView.columns[id].bindCell = (element, index) => - { - var label = GetInitializedElement(element, index); - label.text = getText(label.Entry); - if (getTooltip != null) - label.tooltip = getTooltip(label.Entry); - }; + var split = rootVisualElement.Q(); + split.fixedPaneInitialDimension = split.layout.width / 2; + split.UnregisterCallback(InitializeLayout); } + /* void CreateButton(string name) { var id = name.ToLower(); @@ -190,13 +101,8 @@ void CreateButton(string name) button.text = "Hello"; }; } + */ - T GetInitializedElement(VisualElement element, int index) where T : PackageEntryVisualElement - { - var packageEntryElement = (PackageEntryVisualElement)element; - packageEntryElement.Entry = (PackageEntry)m_ListView.itemsSource[index]; - return (T)packageEntryElement; - } PackageEntry[] GetPackageEntries() { diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs new file mode 100644 index 00000000..5d956d2c --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackages + { + MultiColumnListView m_ListView; + TextField m_Filter; + + List m_UnfilteredEntries; + List m_FilteredEntries; + + internal AndroidLogcatPackages(VisualElement root, List packageEntries) + { + m_UnfilteredEntries = packageEntries; + m_FilteredEntries = new List(); + + m_ListView = root.Q(); + m_Filter = root.Q("filter"); + // TODO: take filter from settings + m_Filter.RegisterValueChangedCallback((s) => + { + FilterBy(s.newValue); + }); + + m_ListView.itemsSource = m_UnfilteredEntries; + m_ListView.sortingEnabled = true; + m_ListView.columnSortingChanged += ColumnSortingChanged; + CreateLabel(nameof(PackageEntry.Name), (e) => e.Name); + CreateLabel(nameof(PackageEntry.Installer), (e) => e.Installer); + CreateLabel(nameof(PackageEntry.UID), (e) => e.UID); + } + + internal void RefreshEntries(List packageEntries) + { + m_UnfilteredEntries = packageEntries; + FilterBy(m_Filter.value); + } + + private void ColumnSortingChanged() + { + var column = m_ListView.sortedColumns.FirstOrDefault(); + m_FilteredEntries.Sort((x, y) => + { + var result = 0; + if (column.columnName.Equals(nameof(PackageEntry.Name), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.Name.CompareTo(y.Name); + } + else if (column.columnName.Equals(nameof(PackageEntry.Installer), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.Installer.CompareTo(y.Installer); + } + else if (column.columnName.Equals(nameof(PackageEntry.UID), StringComparison.InvariantCultureIgnoreCase)) + { + result = x.UID.CompareTo(y.UID); + } + + if (column.direction == SortDirection.Descending) + return result; + return -result; + }); + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + + private void FilterBy(string filter) + { + m_FilteredEntries.Clear(); + if (string.IsNullOrEmpty(filter)) + { + m_FilteredEntries.AddRange(m_UnfilteredEntries); + } + else + { + foreach (var e in m_UnfilteredEntries) + { + if (e.Name.Contains(filter) || + e.Installer.Contains(filter) || + e.UID.Contains(filter)) + m_FilteredEntries.Add(e); + } + } + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + + + void CreateLabel(string name, Func getText, Func getTooltip = null) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => + { + var label = new PackageEntryLabel(); + label.RegisterCallback((e, l) => + { + switch (e.button) + { + case 0: + if (e.clickCount == 2) + { + //OnSelectEntryInListView(l.Entry); + } + break; + } + }, label); + return label; + }; + + m_ListView.columns[id].bindCell = (element, index) => + { + var label = GetInitializedElement(element, index); + label.text = getText(label.Entry); + if (getTooltip != null) + label.tooltip = getTooltip(label.Entry); + }; + } + + T GetInitializedElement(VisualElement element, int index) where T : PackageEntryVisualElement + { + var packageEntryElement = (PackageEntryVisualElement)element; + packageEntryElement.Entry = (PackageEntry)m_ListView.itemsSource[index]; + return (T)packageEntryElement; + } + + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs.meta new file mode 100644 index 00000000..fd7dc37b --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 53a2b8f4589bb5149ac8ed0bbc1c48e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 5d852dfccbb41ce558b79468973df2a37ee4827f Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sun, 12 Feb 2023 19:21:52 +0200 Subject: [PATCH 14/43] doing package properties --- .../Editor/AndroidLogcatPacakgeInfoParser.cs | 4 +- .../Editor/AndroidLogcatPackageEntry.cs | 5 ++ .../Editor/AndroidLogcatPackagesWindow.cs | 29 ++++--- .../Editor/AndroidLogcatUtilities.cs | 24 ++++++ .../UI/AndroidLogcatPackageProperties.cs | 81 +++++++++++++++++++ .../UI/AndroidLogcatPackageProperties.cs.meta | 11 +++ .../Editor/UI/AndroidLogcatPackages.cs | 15 +--- .../Layouts/AndroidLogcatPackagesLayout.uxml | 3 +- .../Editor/AndroidLogcatPackageInfoTests.cs | 2 - 9 files changed, 148 insertions(+), 26 deletions(-) create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs index 415dcf31..1e0c1838 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs @@ -12,7 +12,7 @@ internal class AndroidLogcatPackageInfoParser // Note: Using List instead of Dictionary in case of duplicate keys List> m_Entries; - internal IReadOnlyList> Entries => m_Entries; + internal List> Entries => m_Entries; internal AndroidLogcatPackageInfoParser(string contents, string packageName) { @@ -136,7 +136,7 @@ private string ParsePermissionBlock(string[] lines, int permissionsStart, out in for (int p = permissionsStart + 1; p <= permissionsEnd; p++) { if (value.Length > 0) - value += ", "; + value += "\n"; value += lines[p].Trim(); } blockLength = permissionsEnd - permissionsStart + 1; diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs index a90de5a5..522c1514 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackageEntry.cs @@ -46,5 +46,10 @@ internal void Uninstall() var output = adb.Run(new[] { cmd }, "Unable to uninstall the package"); UnityEngine.Debug.Log(output); } + + public override string ToString() + { + return $"{Name} Installer={Installer} UID={UID}"; + } } } diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 9dbdc09f..3c9f1e79 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -41,11 +41,7 @@ internal class AndroidLogcatPackagesWindow : EditorWindow { AndroidLogcatRuntimeBase m_Runtime; AndroidLogcatPackages m_Packages; - MultiColumnListView m_ListView; - TextField m_Filter; - - List m_UnfilteredEntries; - List m_FilteredEntries; + AndroidLogcatPackageProperties m_PackageProperties; [MenuItem("Test/Test")] static void Init() @@ -60,22 +56,26 @@ private void OnEnable() { if (rootVisualElement == null) throw new NullReferenceException("rooVisualElement is null"); + var label = new Label(); + label.text = "sdsd\nsdsd\n"; + rootVisualElement.Insert(0, label); + rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); + + m_Runtime = AndroidLogcatManager.instance.Runtime; m_Runtime.DeviceQuery.DevicesUpdated += UpdateEntries; - // No device selected yet - m_FilteredEntries = new List(); - m_UnfilteredEntries = new List(); + // TODO: Add query for uxml + clone var tree = AssetDatabase.LoadAssetAtPath("Packages/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml"); tree.CloneTree(rootVisualElement); rootVisualElement.Q().RegisterCallback(InitializeLayout); m_Packages = new AndroidLogcatPackages(rootVisualElement, GetPackageEntries().ToList()); - - rootVisualElement.Insert(0, new IMGUIContainer(DoDebuggingGUI)); + m_Packages.PackageSelected = PackageSelected; + m_PackageProperties = new AndroidLogcatPackageProperties(rootVisualElement); } private void UpdateEntries() @@ -103,6 +103,15 @@ void CreateButton(string name) } */ + void PackageSelected(PackageEntry entry) + { + // TODO: device selection + var entries = AndroidLogcatUtilities.RetrievePackageProperties( + m_Runtime.Tools.ADB, + m_Runtime.DeviceQuery.FirstConnectedDevice, + entry); + m_PackageProperties.RefreshProperties(entries); + } PackageEntry[] GetPackageEntries() { diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs index 64760d14..d1072951 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs @@ -243,6 +243,30 @@ public static PackageEntry[] RetrievePackages(AndroidBridge.ADB adb, IAndroidLog } } + public static List> RetrievePackageProperties(AndroidBridge.ADB adb, IAndroidLogcatDevice device, PackageEntry entry) + { + if (device == null) + return new List>(); + + try + { + var cmd = $"-s {device.Id} shell dumpsys package {entry.Name}"; + AndroidLogcatInternalLog.Log("{0} {1}", adb.GetADBPath(), cmd); + var output = adb.Run(new[] { cmd }, "Unable to retrieve package properties"); + + if (string.IsNullOrEmpty(output)) + return new List>(); + + var parser = new AndroidLogcatPackageInfoParser(output, entry.Name); + return parser.Entries; + } + catch (Exception ex) + { + AndroidLogcatInternalLog.Log(ex.Message); + return new List>(); + } + } + /// /// Return the detail info of the given device. /// diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs new file mode 100644 index 00000000..464f1de2 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackageProperties + { + MultiColumnListView m_ListView; + TextField m_Filter; + + List> m_UnfilteredEntries; + List> m_FilteredEntries; + + internal AndroidLogcatPackageProperties(VisualElement root, List> properties = null) + { + m_UnfilteredEntries = properties; + if (m_UnfilteredEntries == null) + m_UnfilteredEntries = new List>(); + m_FilteredEntries = new List>(); + + m_ListView = root.Q("package_properties"); + m_Filter = root.Q("package_properties_filter"); + + // TODO: take filter from settings + m_Filter.RegisterValueChangedCallback((s) => + { + FilterBy(s.newValue); + }); + + m_ListView.itemsSource = m_UnfilteredEntries; + CreateLabel("name", (e) => e.Key, (e) => $"{e.Key} = {e.Value}"); + CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); + } + + internal void RefreshProperties(List> packageEntries) + { + m_UnfilteredEntries = packageEntries; + FilterBy(m_Filter.value); + } + + private void FilterBy(string filter) + { + m_FilteredEntries.Clear(); + if (string.IsNullOrEmpty(filter)) + { + m_FilteredEntries.AddRange(m_UnfilteredEntries); + } + else + { + foreach (var e in m_UnfilteredEntries) + { + if (e.Key.Contains(filter) || + e.Value.Contains(filter)) + m_FilteredEntries.Add(e); + } + } + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + + void CreateLabel(string name, + Func, string> getText, + Func, string> getTooltip = null) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => new Label(); + m_ListView.columns[id].bindCell = (element, index) => + { + var label = (Label)element; + var entry = (KeyValuePair)m_ListView.itemsSource[index]; + label.text = getText(entry); + if (getTooltip != null) + label.tooltip = getTooltip(entry); + }; + } + + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs.meta new file mode 100644 index 00000000..1bb42e08 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b75bf29df6402247b5ee22cd24c0224 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs index 5d956d2c..e852fa2a 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs @@ -13,12 +13,14 @@ internal class AndroidLogcatPackages List m_UnfilteredEntries; List m_FilteredEntries; + internal Action PackageSelected { set; get; } + internal AndroidLogcatPackages(VisualElement root, List packageEntries) { m_UnfilteredEntries = packageEntries; m_FilteredEntries = new List(); - m_ListView = root.Q(); + m_ListView = root.Q("packages"); m_Filter = root.Q("filter"); // TODO: take filter from settings m_Filter.RegisterValueChangedCallback((s) => @@ -90,7 +92,6 @@ private void FilterBy(string filter) m_ListView.RefreshItems(); } - void CreateLabel(string name, Func getText, Func getTooltip = null) { var id = name.ToLower(); @@ -99,15 +100,7 @@ void CreateLabel(string name, Func getText, Func((e, l) => { - switch (e.button) - { - case 0: - if (e.clickCount == 2) - { - //OnSelectEntryInListView(l.Entry); - } - break; - } + PackageSelected?.Invoke(l.Entry); }, label); return label; }; diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index f2da9123..00c74dd7 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -11,8 +11,9 @@ + - + diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs index ac98b2b0..b1ece0eb 100644 --- a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using System.Text.RegularExpressions; using Unity.Android.Logcat; using System.Linq; using System.Text; -using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics; class AndroidLogcatPacakgeInfoTests { From 077daf427c1a14659c7029086f3a07270240968d Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sun, 12 Feb 2023 21:42:11 +0200 Subject: [PATCH 15/43] Display data as single entries --- .../Editor/AndroidLogcatPacakgeInfoParser.cs | 112 +++++++++++------- .../Editor/AndroidLogcatPackagesWindow.cs | 8 +- .../Editor/AndroidLogcatUtilities.cs | 12 +- .../UI/AndroidLogcatPackageProperties.cs | 30 ++--- .../Layouts/AndroidLogcatPackagesLayout.uxml | 4 +- .../Editor/AndroidLogcatPackageInfoTests.cs | 73 ++++++++---- 6 files changed, 138 insertions(+), 101 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs index 1e0c1838..a1dae7f1 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPacakgeInfoParser.cs @@ -9,52 +9,51 @@ namespace Unity.Android.Logcat internal class AndroidLogcatPackageInfoParser { internal static readonly string FailedKey = "Failed"; - // Note: Using List instead of Dictionary in case of duplicate keys - List> m_Entries; + private string m_Contents; - internal List> Entries => m_Entries; - internal AndroidLogcatPackageInfoParser(string contents, string packageName) + internal AndroidLogcatPackageInfoParser(string contents) { - m_Entries = new List>(); - - contents = contents.Replace("\r\n", "\n"); - - // Note: Keep empty entries, helps us to determine block end - var lines = contents.Split(new[] { '\n' }).ToArray(); - for (int i = 0; i < lines.Length; i++) - { - // Find block start - if (!lines[i].Trim().StartsWith($"Package [{packageName}]")) - continue; + m_Contents = contents.Replace("\r\n", "\n"); + } - var blockStart = i; - var blockEnd = -1; - for (var l = blockStart + 1; l < lines.Length; l++) - { - blockEnd = l; - // Find block end - if (string.IsNullOrEmpty(lines[blockEnd].Trim())) - { - blockEnd--; - break; - } - } + public List ParsePackageInformationAsSingleEntries(string packageName) + { + var lines = GetPackageBlock(packageName); + if (lines == null || lines.Length <= 1) + return new List(); + var strip = lines[1].TakeWhile(c => char.IsWhiteSpace(c)).Count(); + + var entries = lines.Select(c => c.Substring(strip)).ToList(); + entries.RemoveAt(0); + return entries; + } - var length = blockEnd - blockStart + 1; - if (length <= 0) - return; + /// + /// Parses information as [key]=[value] + /// In some cases like permissions or User, it's difficult to present such data + /// For ex., + /// requested permissions: + /// android.permission.INTERNET + /// android.permission.ACCESS_NETWORK_STATE + /// User 0: ceDataInode=311793 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false + /// gids=[3003] + /// runtime permissions: + /// + public List> ParsePackageInformationAsPairs(string packageName) + { + var lines = GetPackageBlock(packageName); + if (lines == null) + return new List>(); - var blockLines = lines.Skip(i).Take(length).ToArray(); - ParsePackageInformation(blockLines, packageName); - return; - } + return ParsePackageInformationAsPairs(lines, packageName); } - private void ParsePackageInformation(string[] lines, string packageName) + private List> ParsePackageInformationAsPairs(string[] lines, string packageName) { + var entries = new List>(); if (lines.Length == 0) - throw new System.Exception("No package info found"); + return entries; var regexPackageName = Regex.Escape(packageName); var title = new Regex($"Package.*{regexPackageName}.*\\:"); @@ -72,7 +71,7 @@ private void ParsePackageInformation(string[] lines, string packageName) { var key = l.Trim(); var values = ParsePermissionBlock(lines, i, out var blockLength); - m_Entries.Add(new KeyValuePair(key, values)); + entries.Add(new KeyValuePair(key, values)); i += blockLength; continue; } @@ -85,16 +84,17 @@ private void ParsePackageInformation(string[] lines, string packageName) var key = result.Groups["key"].Value; var value = result.Groups["value"] == null ? string.Empty : result.Groups["value"].Value; - m_Entries.Add(new KeyValuePair(key, value)); + entries.Add(new KeyValuePair(key, value)); } else { // Failed to parse value, add it as well for easier debugging - m_Entries.Add(new KeyValuePair(FailedKey, l)); + entries.Add(new KeyValuePair(FailedKey, l)); } i++; } + return entries; } private int GetBlockEnd(string[] lines, int blockStart) @@ -136,21 +136,43 @@ private string ParsePermissionBlock(string[] lines, int permissionsStart, out in for (int p = permissionsStart + 1; p <= permissionsEnd; p++) { if (value.Length > 0) - value += "\n"; + value += ", "; value += lines[p].Trim(); } blockLength = permissionsEnd - permissionsStart + 1; return value; } - internal string GetEntriesString() + private string[] GetPackageBlock(string packageName) { - var values = new StringBuilder(); - foreach (var e in Entries) + var lines = m_Contents.Split(new[] { '\n' }).ToArray(); + for (int i = 0; i < lines.Length; i++) { - values.AppendLine($"{e.Key} = {e.Value}"); + // Find block start + if (!lines[i].Trim().StartsWith($"Package [{packageName}]")) + continue; + + var blockStart = i; + var blockEnd = -1; + for (var l = blockStart + 1; l < lines.Length; l++) + { + blockEnd = l; + // Find block end + if (string.IsNullOrEmpty(lines[blockEnd].Trim())) + { + blockEnd--; + break; + } + } + + var length = blockEnd - blockStart + 1; + if (length <= 0) + return Array.Empty(); + + return lines.Skip(i).Take(length).ToArray(); } - return values.ToString(); + + return Array.Empty(); } } } diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index 3c9f1e79..d3205062 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -106,10 +106,10 @@ void CreateButton(string name) void PackageSelected(PackageEntry entry) { // TODO: device selection - var entries = AndroidLogcatUtilities.RetrievePackageProperties( - m_Runtime.Tools.ADB, - m_Runtime.DeviceQuery.FirstConnectedDevice, - entry); + + var parser = new AndroidLogcatPackageInfoParser(AndroidLogcatUtilities.RetrievePackageProperties( + m_Runtime.Tools.ADB, m_Runtime.DeviceQuery.FirstConnectedDevice, entry)); + var entries = parser.ParsePackageInformationAsSingleEntries(entry.Name); m_PackageProperties.RefreshProperties(entries); } diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs index d1072951..a95be011 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatUtilities.cs @@ -243,10 +243,10 @@ public static PackageEntry[] RetrievePackages(AndroidBridge.ADB adb, IAndroidLog } } - public static List> RetrievePackageProperties(AndroidBridge.ADB adb, IAndroidLogcatDevice device, PackageEntry entry) + public static string RetrievePackageProperties(AndroidBridge.ADB adb, IAndroidLogcatDevice device, PackageEntry entry) { if (device == null) - return new List>(); + return string.Empty; try { @@ -254,16 +254,12 @@ public static List> RetrievePackageProperties(Andro AndroidLogcatInternalLog.Log("{0} {1}", adb.GetADBPath(), cmd); var output = adb.Run(new[] { cmd }, "Unable to retrieve package properties"); - if (string.IsNullOrEmpty(output)) - return new List>(); - - var parser = new AndroidLogcatPackageInfoParser(output, entry.Name); - return parser.Entries; + return output; } catch (Exception ex) { AndroidLogcatInternalLog.Log(ex.Message); - return new List>(); + return string.Empty; } } diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs index 464f1de2..9ea8e784 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs @@ -10,15 +10,15 @@ internal class AndroidLogcatPackageProperties MultiColumnListView m_ListView; TextField m_Filter; - List> m_UnfilteredEntries; - List> m_FilteredEntries; + List m_UnfilteredEntries; + List m_FilteredEntries; - internal AndroidLogcatPackageProperties(VisualElement root, List> properties = null) + internal AndroidLogcatPackageProperties(VisualElement root, List properties = null) { m_UnfilteredEntries = properties; if (m_UnfilteredEntries == null) - m_UnfilteredEntries = new List>(); - m_FilteredEntries = new List>(); + m_UnfilteredEntries = new List(); + m_FilteredEntries = new List(); m_ListView = root.Q("package_properties"); m_Filter = root.Q("package_properties_filter"); @@ -30,11 +30,11 @@ internal AndroidLogcatPackageProperties(VisualElement root, List e.Key, (e) => $"{e.Key} = {e.Value}"); - CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); + CreateLabel("value"); + // CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); } - internal void RefreshProperties(List> packageEntries) + internal void RefreshProperties(List packageEntries) { m_UnfilteredEntries = packageEntries; FilterBy(m_Filter.value); @@ -51,8 +51,7 @@ private void FilterBy(string filter) { foreach (var e in m_UnfilteredEntries) { - if (e.Key.Contains(filter) || - e.Value.Contains(filter)) + if (e.Contains(filter)) m_FilteredEntries.Add(e); } } @@ -61,19 +60,16 @@ private void FilterBy(string filter) m_ListView.RefreshItems(); } - void CreateLabel(string name, - Func, string> getText, - Func, string> getTooltip = null) + void CreateLabel(string name) { var id = name.ToLower(); m_ListView.columns[id].makeCell = () => new Label(); m_ListView.columns[id].bindCell = (element, index) => { var label = (Label)element; - var entry = (KeyValuePair)m_ListView.itemsSource[index]; - label.text = getText(entry); - if (getTooltip != null) - label.tooltip = getTooltip(entry); + var entry = (string)m_ListView.itemsSource[index]; + label.text = entry; + label.tooltip = entry; }; } diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index 00c74dd7..f54bcf18 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -12,11 +12,9 @@ - - - + diff --git a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs index b1ece0eb..ecc230fa 100644 --- a/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs +++ b/com.unity.mobile.android-logcat/Tests/Editor/AndroidLogcatPackageInfoTests.cs @@ -15,12 +15,12 @@ private void AssertDictionary(Dictionary dictionary, string key, Assert.IsTrue(dictionary[key].Equals(value), $"Key = {key}, expected value '{value}', but got '{dictionary[key]}'"); } - private Dictionary EntriesToDictionary(AndroidLogcatPackageInfoParser parser) + private Dictionary EntriesToDictionary(List> entries) { - Assert.That(parser.Entries.Count, Is.GreaterThan(0)); + Assert.That(entries.Count, Is.GreaterThan(0)); var failedParsings = new StringBuilder(); - foreach (var e in parser.Entries) + foreach (var e in entries) { if (e.Key.Equals(AndroidLogcatPackageInfoParser.FailedKey)) failedParsings.AppendLine(e.Value); @@ -28,16 +28,22 @@ private Dictionary EntriesToDictionary(AndroidLogcatPackageInfoP Assert.IsTrue(failedParsings.Length == 0, $"Failed to parse some values:\n{failedParsings}"); - Dictionary entries; + Dictionary dictionaryEntries; try { - entries = parser.Entries.ToDictionary(x => x.Key, x => x.Value); + dictionaryEntries = entries.ToDictionary(x => x.Key, x => x.Value); } catch (Exception ex) { - throw new Exception($"Failed to form dictionary from:\n{parser.GetEntriesString()}", ex); + var values = new StringBuilder(); + foreach (var e in entries) + { + values.AppendLine($"{e.Key} = {e.Value}"); + } + + throw new Exception($"Failed to form dictionary from:\n{values}", ex); } - return entries; + return dictionaryEntries; } // adb shell dumpsys package @@ -83,8 +89,9 @@ public void CanParsePackageInfo() gids=[3003] runtime permissions: "; - var parser = new AndroidLogcatPackageInfoParser(contents, packageName); - var entries = EntriesToDictionary(parser); + // Note: User 0 parsing looks ugly and incorrect + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = EntriesToDictionary(parser.ParsePackageInformationAsPairs(packageName)); AssertDictionary(entries, "pkg", $"Package{{d78b8ca {packageName}}}"); AssertDictionary(entries, "codePath", $"/data/app/~~ur3u-ye7dI8GpfIRkeYy7Q==/{packageName}-bzIOds7vr6jRoCaEw1TacQ=="); @@ -98,24 +105,25 @@ public void CanParsePackageInfo() public void CanParseEmpty() { var packageName = "com.dummy.dummy"; - var permissionsEndWithEndLine = @$" + var contents = @$" Package [{packageName}] (ffc5f27):"; - var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithEndLine, packageName); - Assert.AreEqual(0, parser.Entries.Count); + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = parser.ParsePackageInformationAsPairs(packageName); + Assert.AreEqual(0, entries.Count); } [Test] public void CanParsePermissionsWithEndLine() { var packageName = "com.dummy.dummy"; - var permissionsEndWithEndLine = @$" + var contents = @$" Package [{packageName}] (ffc5f27): requested permissions: android.permission.INTERNET android.permission.ACCESS_NETWORK_STATE"; - var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithEndLine, packageName); - var entries = EntriesToDictionary(parser); + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = EntriesToDictionary(parser.ParsePackageInformationAsPairs(packageName)); AssertDictionary(entries, "requested permissions:", $"android.permission.INTERNET, android.permission.ACCESS_NETWORK_STATE"); } @@ -124,14 +132,14 @@ public void CanParsePermissionsWithEndLine() public void CanParsePermissionsWithExtraLine() { var packageName = "com.dummy.dummy"; - var permissionsEndWithExtraLine = @$" + var contents = @$" Package [{packageName}] (ffc5f27): requested permissions: android.permission.INTERNET android.permission.ACCESS_NETWORK_STATE "; - var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithExtraLine, packageName); - var entries = EntriesToDictionary(parser); + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = EntriesToDictionary(parser.ParsePackageInformationAsPairs(packageName)); AssertDictionary(entries, "requested permissions:", $"android.permission.INTERNET, android.permission.ACCESS_NETWORK_STATE"); } @@ -140,12 +148,12 @@ public void CanParsePermissionsWithExtraLine() public void CanParsePermissionsEmpty() { var packageName = "com.dummy.dummy"; - var permissionsEndWithExtraLine = @$" + var contents = @$" Package [{packageName}] (ffc5f27): requested permissions:"; - var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithExtraLine, packageName); - var entries = EntriesToDictionary(parser); + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = EntriesToDictionary(parser.ParsePackageInformationAsPairs(packageName)); AssertDictionary(entries, "requested permissions:", string.Empty); } @@ -154,13 +162,30 @@ public void CanParsePermissionsEmpty() public void CanParsePermissionsEmptyWithExtraLine() { var packageName = "com.dummy.dummy"; - var permissionsEndWithExtraLine = @$" + var contents = @$" Package [{packageName}] (ffc5f27): requested permissions: "; - var parser = new AndroidLogcatPackageInfoParser(permissionsEndWithExtraLine, packageName); - var entries = EntriesToDictionary(parser); + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = EntriesToDictionary(parser.ParsePackageInformationAsPairs(packageName)); AssertDictionary(entries, "requested permissions:", string.Empty); } + + [Test] + public void CanParsePackageInfoAsSingleEntries() + { + var packageName = "com.DefaultCompany.AndroidEmptyGameActivity"; + var contents = @$" Some other data + + Package [{packageName}] (ffc5f27): + userId=10198 + sdsd"; + + var parser = new AndroidLogcatPackageInfoParser(contents); + var entries = parser.ParsePackageInformationAsSingleEntries(packageName); + Assert.That(entries.Count, Is.EqualTo(2)); + StringAssert.AreEqualIgnoringCase("userId=10198", entries[0]); + StringAssert.AreEqualIgnoringCase("sdsd", entries[1]); + } } From 838a5cee509498ad500d6a0284e2040a1f2ce7c8 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sun, 12 Feb 2023 22:21:42 +0200 Subject: [PATCH 16/43] Add margins --- .../Editor/UI/AndroidLogcatPackageProperties.cs | 8 +++++++- .../Editor/UI/AndroidLogcatPackages.cs | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs index 9ea8e784..01456e41 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs @@ -63,7 +63,13 @@ private void FilterBy(string filter) void CreateLabel(string name) { var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => new Label(); + m_ListView.columns[id].makeCell = () => new Label() + { + style = + { + marginLeft = 5.0f + } + }; m_ListView.columns[id].bindCell = (element, index) => { var label = (Label)element; diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs index e852fa2a..5be40c88 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs @@ -98,6 +98,7 @@ void CreateLabel(string name, Func getText, Func { var label = new PackageEntryLabel(); + label.style.marginLeft = 5.0f; label.RegisterCallback((e, l) => { PackageSelected?.Invoke(l.Entry); From c91365022cfa2a09418b0f57dd387910153f36b4 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sun, 12 Feb 2023 22:23:30 +0200 Subject: [PATCH 17/43] slightly fix tooltip --- .../Editor/UI/AndroidLogcatPackageProperties.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs index 01456e41..c71a859f 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs @@ -75,7 +75,7 @@ void CreateLabel(string name) var label = (Label)element; var entry = (string)m_ListView.itemsSource[index]; label.text = entry; - label.tooltip = entry; + label.tooltip = entry.Trim(); }; } From b92fe7f0cebf7bb21308f16b305f6698eee2bbe5 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Thu, 23 Feb 2023 22:10:26 +0200 Subject: [PATCH 18/43] Move packages to its own folder --- .../Editor/UI/Packages.meta | 8 + .../AndroidLogcatPackageLabel.cs | 0 .../AndroidLogcatPackageLabel.cs.meta | 0 .../AndroidLogcatPackageProperties.cs | 156 +++++++++--------- .../AndroidLogcatPackageProperties.cs.meta | 0 .../{ => Packages}/AndroidLogcatPackages.cs | 0 .../AndroidLogcatPackages.cs.meta | 0 7 files changed, 86 insertions(+), 78 deletions(-) create mode 100644 com.unity.mobile.android-logcat/Editor/UI/Packages.meta rename com.unity.mobile.android-logcat/Editor/UI/{ => Packages}/AndroidLogcatPackageLabel.cs (100%) rename com.unity.mobile.android-logcat/Editor/UI/{ => Packages}/AndroidLogcatPackageLabel.cs.meta (100%) rename com.unity.mobile.android-logcat/Editor/UI/{ => Packages}/AndroidLogcatPackageProperties.cs (96%) rename com.unity.mobile.android-logcat/Editor/UI/{ => Packages}/AndroidLogcatPackageProperties.cs.meta (100%) rename com.unity.mobile.android-logcat/Editor/UI/{ => Packages}/AndroidLogcatPackages.cs (100%) rename com.unity.mobile.android-logcat/Editor/UI/{ => Packages}/AndroidLogcatPackages.cs.meta (100%) diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages.meta b/com.unity.mobile.android-logcat/Editor/UI/Packages.meta new file mode 100644 index 00000000..6de9c1b5 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 598088db5abdbee4ab7e54a093b55c5c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs similarity index 100% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs rename to com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs.meta similarity index 100% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageLabel.cs.meta rename to com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs similarity index 96% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs rename to com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs index c71a859f..8d26b665 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs @@ -1,83 +1,83 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine.UIElements; - -namespace Unity.Android.Logcat -{ - internal class AndroidLogcatPackageProperties - { - MultiColumnListView m_ListView; - TextField m_Filter; - - List m_UnfilteredEntries; - List m_FilteredEntries; - - internal AndroidLogcatPackageProperties(VisualElement root, List properties = null) - { - m_UnfilteredEntries = properties; - if (m_UnfilteredEntries == null) - m_UnfilteredEntries = new List(); - m_FilteredEntries = new List(); - - m_ListView = root.Q("package_properties"); - m_Filter = root.Q("package_properties_filter"); - - // TODO: take filter from settings - m_Filter.RegisterValueChangedCallback((s) => - { - FilterBy(s.newValue); - }); - - m_ListView.itemsSource = m_UnfilteredEntries; - CreateLabel("value"); - // CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); - } - - internal void RefreshProperties(List packageEntries) - { - m_UnfilteredEntries = packageEntries; - FilterBy(m_Filter.value); - } - - private void FilterBy(string filter) - { - m_FilteredEntries.Clear(); - if (string.IsNullOrEmpty(filter)) - { - m_FilteredEntries.AddRange(m_UnfilteredEntries); - } - else - { - foreach (var e in m_UnfilteredEntries) - { - if (e.Contains(filter)) - m_FilteredEntries.Add(e); - } - } - - m_ListView.itemsSource = m_FilteredEntries; - m_ListView.RefreshItems(); - } - - void CreateLabel(string name) - { - var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => new Label() +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackageProperties + { + MultiColumnListView m_ListView; + TextField m_Filter; + + List m_UnfilteredEntries; + List m_FilteredEntries; + + internal AndroidLogcatPackageProperties(VisualElement root, List properties = null) + { + m_UnfilteredEntries = properties; + if (m_UnfilteredEntries == null) + m_UnfilteredEntries = new List(); + m_FilteredEntries = new List(); + + m_ListView = root.Q("package_properties"); + m_Filter = root.Q("package_properties_filter"); + + // TODO: take filter from settings + m_Filter.RegisterValueChangedCallback((s) => + { + FilterBy(s.newValue); + }); + + m_ListView.itemsSource = m_UnfilteredEntries; + CreateLabel("value"); + // CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); + } + + internal void RefreshProperties(List packageEntries) + { + m_UnfilteredEntries = packageEntries; + FilterBy(m_Filter.value); + } + + private void FilterBy(string filter) + { + m_FilteredEntries.Clear(); + if (string.IsNullOrEmpty(filter)) + { + m_FilteredEntries.AddRange(m_UnfilteredEntries); + } + else + { + foreach (var e in m_UnfilteredEntries) + { + if (e.Contains(filter)) + m_FilteredEntries.Add(e); + } + } + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + + void CreateLabel(string name) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => new Label() { style = { marginLeft = 5.0f } - }; - m_ListView.columns[id].bindCell = (element, index) => - { - var label = (Label)element; - var entry = (string)m_ListView.itemsSource[index]; - label.text = entry; - label.tooltip = entry.Trim(); - }; - } - - } -} + }; + m_ListView.columns[id].bindCell = (element, index) => + { + var label = (Label)element; + var entry = (string)m_ListView.itemsSource[index]; + label.text = entry; + label.tooltip = entry.Trim(); + }; + } + + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs.meta similarity index 100% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackageProperties.cs.meta rename to com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs similarity index 100% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs rename to com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs diff --git a/com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs.meta similarity index 100% rename from com.unity.mobile.android-logcat/Editor/UI/AndroidLogcatPackages.cs.meta rename to com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs.meta From e99f457c58830fd2faf6a5ff51fce8f03a7d96bd Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Thu, 23 Feb 2023 22:36:20 +0200 Subject: [PATCH 19/43] context menu for packages --- .../UI/Packages/AndroidLogcatPackageLabel.cs | 4 + .../AndroidLogcatPackageProperties.cs | 166 +++++++++--------- .../UI/Packages/AndroidLogcatPackages.cs | 56 ++++++ 3 files changed, 143 insertions(+), 83 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs index 4dffd0a7..36d7bab5 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs @@ -5,15 +5,19 @@ namespace Unity.Android.Logcat interface PackageEntryVisualElement { PackageEntry Entry { set; get; } + int Index { set; get; } } class PackageEntryLabel : Label, PackageEntryVisualElement { public PackageEntry Entry { set; get; } + public int Index { set; get; } } class PackageEntryButton : Button, PackageEntryVisualElement { public PackageEntry Entry { set; get; } + + public int Index { set; get; } } } diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs index 8d26b665..1ced3889 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs @@ -1,83 +1,83 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine.UIElements; - -namespace Unity.Android.Logcat -{ - internal class AndroidLogcatPackageProperties - { - MultiColumnListView m_ListView; - TextField m_Filter; - - List m_UnfilteredEntries; - List m_FilteredEntries; - - internal AndroidLogcatPackageProperties(VisualElement root, List properties = null) - { - m_UnfilteredEntries = properties; - if (m_UnfilteredEntries == null) - m_UnfilteredEntries = new List(); - m_FilteredEntries = new List(); - - m_ListView = root.Q("package_properties"); - m_Filter = root.Q("package_properties_filter"); - - // TODO: take filter from settings - m_Filter.RegisterValueChangedCallback((s) => - { - FilterBy(s.newValue); - }); - - m_ListView.itemsSource = m_UnfilteredEntries; - CreateLabel("value"); - // CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); - } - - internal void RefreshProperties(List packageEntries) - { - m_UnfilteredEntries = packageEntries; - FilterBy(m_Filter.value); - } - - private void FilterBy(string filter) - { - m_FilteredEntries.Clear(); - if (string.IsNullOrEmpty(filter)) - { - m_FilteredEntries.AddRange(m_UnfilteredEntries); - } - else - { - foreach (var e in m_UnfilteredEntries) - { - if (e.Contains(filter)) - m_FilteredEntries.Add(e); - } - } - - m_ListView.itemsSource = m_FilteredEntries; - m_ListView.RefreshItems(); - } - - void CreateLabel(string name) - { - var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => new Label() - { - style = - { - marginLeft = 5.0f - } - }; - m_ListView.columns[id].bindCell = (element, index) => - { - var label = (Label)element; - var entry = (string)m_ListView.itemsSource[index]; - label.text = entry; - label.tooltip = entry.Trim(); - }; - } - - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackageProperties + { + MultiColumnListView m_ListView; + TextField m_Filter; + + List m_UnfilteredEntries; + List m_FilteredEntries; + + internal AndroidLogcatPackageProperties(VisualElement root, List properties = null) + { + m_UnfilteredEntries = properties; + if (m_UnfilteredEntries == null) + m_UnfilteredEntries = new List(); + m_FilteredEntries = new List(); + + m_ListView = root.Q("package_properties"); + m_Filter = root.Q("package_properties_filter"); + + // TODO: take filter from settings + m_Filter.RegisterValueChangedCallback((s) => + { + FilterBy(s.newValue); + }); + + m_ListView.itemsSource = m_UnfilteredEntries; + CreateLabel("value"); + // CreateLabel("value", (e) => e.Value, (e) => $"{e.Key} = {e.Value}"); + } + + internal void RefreshProperties(List packageEntries) + { + m_UnfilteredEntries = packageEntries; + FilterBy(m_Filter.value); + } + + private void FilterBy(string filter) + { + m_FilteredEntries.Clear(); + if (string.IsNullOrEmpty(filter)) + { + m_FilteredEntries.AddRange(m_UnfilteredEntries); + } + else + { + foreach (var e in m_UnfilteredEntries) + { + if (e.Contains(filter)) + m_FilteredEntries.Add(e); + } + } + + m_ListView.itemsSource = m_FilteredEntries; + m_ListView.RefreshItems(); + } + + void CreateLabel(string name) + { + var id = name.ToLower(); + m_ListView.columns[id].makeCell = () => new Label() + { + style = + { + marginLeft = 5.0f + } + }; + m_ListView.columns[id].bindCell = (element, index) => + { + var label = (Label)element; + var entry = (string)m_ListView.itemsSource[index]; + label.text = entry; + label.tooltip = entry.Trim(); + }; + } + + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs index 5be40c88..bfccb2a9 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackages.cs @@ -1,12 +1,23 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; +using UnityEditor; +using UnityEngine; using UnityEngine.UIElements; namespace Unity.Android.Logcat { internal class AndroidLogcatPackages { + enum PackagesContextMenu + { + CopyPackageName, + CopyPackageInfo, + CopyAll + } + + MultiColumnListView m_ListView; TextField m_Filter; @@ -101,8 +112,52 @@ void CreateLabel(string name, Func getText, Func((e, l) => { + // By default only left click applies the selection, select with right click too + if (e.button == 1) + m_ListView.SetSelectionWithoutNotify(new[] { l.Index }); + PackageSelected?.Invoke(l.Entry); }, label); + + label.RegisterCallback((e, l) => + { + if (e.button != 1) + return; + + m_ListView.SetSelection(l.Index); + + var contextMenu = new AndroidContextMenu(); + contextMenu.Add(PackagesContextMenu.CopyPackageName, "Copy Package Name"); + contextMenu.Add(PackagesContextMenu.CopyPackageInfo, "Copy Package Information"); + contextMenu.Add(PackagesContextMenu.CopyAll, "Copy All"); + + contextMenu.Show(e.mousePosition, (userData, options, selected) => + { + var sender = (AndroidContextMenu)userData; + var item = sender.GetItemAt(selected); + if (item == null) + return; + + switch (item.Item) + { + case PackagesContextMenu.CopyPackageName: + EditorGUIUtility.systemCopyBuffer = l.Entry.Name; + break; + case PackagesContextMenu.CopyPackageInfo: + EditorGUIUtility.systemCopyBuffer = l.Entry.ToString(); + break; + case PackagesContextMenu.CopyAll: + var data = new StringBuilder(); + foreach (var p in m_FilteredEntries) + { + data.AppendLine(p.ToString()); + } + EditorGUIUtility.systemCopyBuffer = data.ToString(); + break; + } + }); + + }, label); return label; }; @@ -119,6 +174,7 @@ T GetInitializedElement(VisualElement element, int index) where T : PackageEn { var packageEntryElement = (PackageEntryVisualElement)element; packageEntryElement.Entry = (PackageEntry)m_ListView.itemsSource[index]; + packageEntryElement.Index = index; return (T)packageEntryElement; } From 05b30d285af30f166aa94653298d2cffcf2d3858 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Thu, 23 Feb 2023 22:48:38 +0200 Subject: [PATCH 20/43] context menu for package properties --- .../UI/Packages/AndroidLogcatPackageLabel.cs | 6 ++ .../AndroidLogcatPackageProperties.cs | 63 +++++++++++++++++-- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs index 36d7bab5..a8bb87fd 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageLabel.cs @@ -20,4 +20,10 @@ class PackageEntryButton : Button, PackageEntryVisualElement public int Index { set; get; } } + + class PackagePropertyLabel : Label + { + public int Index { set; get; } + } + } diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs index 1ced3889..341c3246 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs @@ -2,11 +2,19 @@ using System.Collections.Generic; using System.Linq; using UnityEngine.UIElements; +using UnityEditor; +using System.Text; namespace Unity.Android.Logcat { internal class AndroidLogcatPackageProperties { + enum PackagePropertiesContextMenu + { + CopyProperty, + CopyAll + } + MultiColumnListView m_ListView; TextField m_Filter; @@ -63,21 +71,64 @@ private void FilterBy(string filter) void CreateLabel(string name) { var id = name.ToLower(); - m_ListView.columns[id].makeCell = () => new Label() + m_ListView.columns[id].makeCell = () => { - style = + var label = new PackagePropertyLabel(); + label.style.marginLeft = 5.0f; + + label.RegisterCallback((e, l) => { - marginLeft = 5.0f - } + if (e.button == 1) + m_ListView.SetSelectionWithoutNotify(new[] { l.Index }); + + }, label); + + label.RegisterCallback((e, l) => + { + if (e.button != 1) + return; + + m_ListView.SetSelection(l.Index); + + var contextMenu = new AndroidContextMenu(); + contextMenu.Add(PackagePropertiesContextMenu.CopyProperty, "Copy Property"); + contextMenu.Add(PackagePropertiesContextMenu.CopyAll, "Copy All"); + + contextMenu.Show(e.mousePosition, (userData, options, selected) => + { + var sender = (AndroidContextMenu)userData; + var item = sender.GetItemAt(selected); + if (item == null) + return; + + switch (item.Item) + { + case PackagePropertiesContextMenu.CopyProperty: + EditorGUIUtility.systemCopyBuffer = l.text; + break; + case PackagePropertiesContextMenu.CopyAll: + var data = new StringBuilder(); + foreach (var p in m_FilteredEntries) + { + data.AppendLine(p.ToString()); + } + EditorGUIUtility.systemCopyBuffer = data.ToString(); + break; + } + }); + + }, label); + + return label; }; m_ListView.columns[id].bindCell = (element, index) => { - var label = (Label)element; + var label = (PackagePropertyLabel)element; var entry = (string)m_ListView.itemsSource[index]; label.text = entry; label.tooltip = entry.Trim(); + label.Index = index; }; } - } } From 9bf7dc36e328ada683abcef517e830930987b032 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Thu, 23 Feb 2023 23:49:10 +0200 Subject: [PATCH 21/43] Utilities --- .../Editor/AndroidLogcatPackagesWindow.cs | 2 + .../Layouts/AndroidLogcatPackagesLayout.uxml | 21 ++++++-- .../AndroidLogcatPackageProperties.cs | 1 + .../Packages/AndroidLogcatPackageUtilities.cs | 48 +++++++++++++++++++ .../AndroidLogcatPackageUtilities.cs.meta | 11 +++++ 5 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs create mode 100644 com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs.meta diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs index d3205062..c7001a8b 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatPackagesWindow.cs @@ -42,6 +42,7 @@ internal class AndroidLogcatPackagesWindow : EditorWindow AndroidLogcatRuntimeBase m_Runtime; AndroidLogcatPackages m_Packages; AndroidLogcatPackageProperties m_PackageProperties; + AndroidLogcatPackageUtilities m_PackageUtilities; [MenuItem("Test/Test")] static void Init() @@ -76,6 +77,7 @@ private void OnEnable() m_Packages = new AndroidLogcatPackages(rootVisualElement, GetPackageEntries().ToList()); m_Packages.PackageSelected = PackageSelected; m_PackageProperties = new AndroidLogcatPackageProperties(rootVisualElement); + m_PackageUtilities = new AndroidLogcatPackageUtilities(rootVisualElement); } private void UpdateEntries() diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index f54bcf18..e25934a8 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -1,4 +1,4 @@ - + @@ -11,16 +11,27 @@ + + + + + + + + + + + + + + + - - - - diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs index 341c3246..a541d440 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageProperties.cs @@ -4,6 +4,7 @@ using UnityEngine.UIElements; using UnityEditor; using System.Text; +using UnityEditor.UIElements; namespace Unity.Android.Logcat { diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs new file mode 100644 index 00000000..623f5626 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine.UIElements; +using UnityEditor; +using System.Text; +using UnityEditor.UIElements; +using UnityEngine; + +namespace Unity.Android.Logcat +{ + internal class AndroidLogcatPackageUtilities + { + enum PackageUtilitiesTab + { + LaunchOptions, + Others + } + + ToolbarToggle m_LaunchOptions; + ToolbarToggle m_Others; + VisualElement m_TabLaunchOptions; + VisualElement m_TabOthers; + + internal AndroidLogcatPackageUtilities(VisualElement root) + { + m_LaunchOptions = root.Q("package-launch-options"); + m_Others = root.Q("package-others"); + + m_LaunchOptions.RegisterValueChangedCallback((v) => SelectTab(PackageUtilitiesTab.LaunchOptions)); + m_Others.RegisterValueChangedCallback((v) => SelectTab(PackageUtilitiesTab.Others)); + + m_TabLaunchOptions = root.Q("package-tab-launch-options"); + m_TabOthers = root.Q("package-tab-others"); + + // TODO: take from settings + SelectTab(PackageUtilitiesTab.LaunchOptions); + } + + private void SelectTab(PackageUtilitiesTab tab) + { + m_LaunchOptions.SetValueWithoutNotify(tab == PackageUtilitiesTab.LaunchOptions); + m_Others.SetValueWithoutNotify(tab == PackageUtilitiesTab.Others); + m_TabLaunchOptions.visible = tab == PackageUtilitiesTab.LaunchOptions; + m_TabOthers.visible = tab == PackageUtilitiesTab.Others; + } + } +} diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs.meta b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs.meta new file mode 100644 index 00000000..b63ec2a0 --- /dev/null +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e4b53ba6212c1743ae5911226ccf2c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 76c52404a264d4ef95c58d9d5c3d0ad1162b6795 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Fri, 24 Feb 2023 23:49:04 +0200 Subject: [PATCH 22/43] Doing tabs --- .../Layouts/AndroidLogcatPackagesLayout.uxml | 79 ++++++++++--------- .../Packages/AndroidLogcatPackageUtilities.cs | 15 +++- 2 files changed, 55 insertions(+), 39 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index e25934a8..4fe0c77e 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -1,37 +1,42 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs index 623f5626..b94131b8 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs @@ -19,11 +19,13 @@ enum PackageUtilitiesTab ToolbarToggle m_LaunchOptions; ToolbarToggle m_Others; + VisualElement m_TabContents; VisualElement m_TabLaunchOptions; VisualElement m_TabOthers; internal AndroidLogcatPackageUtilities(VisualElement root) { + m_TabContents = root.Q("package-tabs-contents"); m_LaunchOptions = root.Q("package-launch-options"); m_Others = root.Q("package-others"); @@ -41,8 +43,17 @@ private void SelectTab(PackageUtilitiesTab tab) { m_LaunchOptions.SetValueWithoutNotify(tab == PackageUtilitiesTab.LaunchOptions); m_Others.SetValueWithoutNotify(tab == PackageUtilitiesTab.Others); - m_TabLaunchOptions.visible = tab == PackageUtilitiesTab.LaunchOptions; - m_TabOthers.visible = tab == PackageUtilitiesTab.Others; + + var toRemove = m_TabContents.Children().ToArray(); + foreach (var c in toRemove) + m_TabContents.Remove(c); + + if (tab == PackageUtilitiesTab.LaunchOptions) + m_TabContents.Add(m_TabLaunchOptions); + if (tab == PackageUtilitiesTab.Others) + m_TabContents.Add(m_TabOthers); + // m_TabLaunchOptions.SetEnabled(); + //m_TabOthers.SetEnabled(tab == PackageUtilitiesTab.Others); } } } From 98617cd696fe4b1b1d0f8c09da89bc98f6773792 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Fri, 24 Feb 2023 23:49:38 +0200 Subject: [PATCH 23/43] Doing tabs --- .../Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index 4fe0c77e..129e1d02 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -19,7 +19,7 @@ - + From 4274212cc719b1ae4b72197bac6328b50b4a0d95 Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Fri, 24 Feb 2023 23:58:58 +0200 Subject: [PATCH 24/43] Doing tabs, put them in a box --- .../Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index 129e1d02..4b227ce8 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -18,7 +18,7 @@ - + @@ -29,7 +29,7 @@ - + From fc3d77e7c251f0d7e566804efba391c48a1cf3ad Mon Sep 17 00:00:00 2001 From: Tomas Dirvanauskas Date: Sat, 25 Feb 2023 00:22:15 +0200 Subject: [PATCH 25/43] doing buttons --- .../Editor/AndroidLogcatDevice.cs | 20 +++++ .../Layouts/AndroidLogcatPackagesLayout.uxml | 84 +++++++++---------- .../Packages/AndroidLogcatPackageUtilities.cs | 18 +++- 3 files changed, 78 insertions(+), 44 deletions(-) diff --git a/com.unity.mobile.android-logcat/Editor/AndroidLogcatDevice.cs b/com.unity.mobile.android-logcat/Editor/AndroidLogcatDevice.cs index f475ef1f..f1590ad3 100644 --- a/com.unity.mobile.android-logcat/Editor/AndroidLogcatDevice.cs +++ b/com.unity.mobile.android-logcat/Editor/AndroidLogcatDevice.cs @@ -45,6 +45,11 @@ internal enum DeviceState internal abstract string ShortDisplayName { get; } + internal virtual void SendKey(AndroidKeyCode keyCode) + { + + } + internal bool SupportsFilteringByPid { get { return OSVersion >= kAndroidVersion70; } @@ -83,12 +88,14 @@ internal class AndroidLogcatDevice : IAndroidLogcatDevice { private string m_Id; private AndroidBridge.AndroidDevice m_Device; + private AndroidBridge.ADB m_ADB; private Version m_Version; private string m_DisplayName; internal AndroidLogcatDevice(AndroidBridge.ADB adb, string deviceId) { + m_ADB = adb; m_Id = deviceId; if (adb == null) @@ -198,5 +205,18 @@ internal override string ShortDisplayName return Id; } } + + internal override void SendKey(AndroidKeyCode keyCode) + { + m_ADB.Run(new[] + { + "-s", + Id, + "shell", + "input", + "keyevent", + ((int)keyCode).ToString() + }, $"Failed to send key event '{keyCode}'"); + } } } diff --git a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml index 4b227ce8..3f808e69 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml +++ b/com.unity.mobile.android-logcat/Editor/UI/Layouts/AndroidLogcatPackagesLayout.uxml @@ -1,42 +1,42 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs index b94131b8..e14ae776 100644 --- a/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs +++ b/com.unity.mobile.android-logcat/Editor/UI/Packages/AndroidLogcatPackageUtilities.cs @@ -35,6 +35,22 @@ internal AndroidLogcatPackageUtilities(VisualElement root) m_TabLaunchOptions = root.Q("package-tab-launch-options"); m_TabOthers = root.Q("package-tab-others"); + root.Q