예제 #1
0
 /// <summary>
 /// Executes a shell command on the device.
 /// </summary>
 /// <param name="device">
 /// The device on which to run the command.
 /// </param>
 /// <param name="command">
 /// The command to execute.
 /// </param>
 /// <param name="receiver">
 /// Optionally, a <see cref="IShellOutputReceiver"/> that processes the command output.
 /// </param>
 public static void ExecuteShellCommand(this DeviceData device, string command, IShellOutputReceiver receiver)
 {
     device.ExecuteShellCommand(AdbClient.Instance, command, receiver);
 }
        /// <summary>
        /// Lists all processes running on the device.
        /// </summary>
        /// <param name="device">
        /// The device on which to list the processes that are running.
        /// </param>
        /// <returns>
        /// An <see cref="IEnumerable{AndroidProcess}"/> that will iterate over all
        /// processes that are currently running on the device.
        /// </returns>
        public static IEnumerable <AndroidProcess> ListProcesses(this DeviceData device)
        {
            // There are a couple of gotcha's when listing processes on an Android device.
            // One way would be to run ps and parse the output. However, the output of
            // ps differents from Android version to Android version, is not delimited, nor
            // entirely fixed length, and some of the fields can be empty, so it's almost impossible
            // to parse correctly.
            //
            // The alternative is to directly read the values in /proc/[pid], pretty much like ps
            // does (see https://android.googlesource.com/platform/system/core/+/master/toolbox/ps.c).
            //
            // The easiest way to do the directory listings would be to use the SyncService; unfortunately,
            // the sync service doesn't work very well with /proc/ so we're back to using ls and taking it
            // from there.
            List <AndroidProcess> processes = new List <AndroidProcess>();

            // List all processes by doing ls /proc/.
            // All subfolders which are completely numeric are PIDs
            ConsoleOutputReceiver receiver = new ConsoleOutputReceiver();

            device.ExecuteShellCommand("/system/bin/ls /proc/", receiver);

            Collection <int> pids = new Collection <int>();

            using (StringReader reader = new StringReader(receiver.ToString()))
            {
                while (reader.Peek() > 0)
                {
                    string line = reader.ReadLine();

                    if (!line.All(c => char.IsDigit(c)))
                    {
                        continue;
                    }

                    var pid = int.Parse(line);

                    pids.Add(pid);
                }
            }

            // For each pid, we can get /proc/[pid]/stat, which contains the process information in a well-defined
            // format - see http://man7.org/linux/man-pages/man5/proc.5.html.
            // Doing cat on each file one by one takes too much time. Doing cat on all of them at the same time doesn't work
            // either, because the command line would be too long.
            // So we do it 50 processes at at time.
            StringBuilder         catBuilder            = new StringBuilder();
            ProcessOutputReceiver processOutputReceiver = new ProcessOutputReceiver();

            for (int i = 0; i < pids.Count; i++)
            {
                if (i % 50 == 0)
                {
                    catBuilder.Clear();
                    catBuilder.Append("cat ");
                }

                catBuilder.Append($"/proc/{pids[i]}/stat ");

                if (i > 0 && (i % 50 == 0 || i == pids.Count - 1))
                {
                    device.ExecuteShellCommand(catBuilder.ToString(), processOutputReceiver);
                }
            }

            processOutputReceiver.Flush();

            return(processOutputReceiver.Processes);
        }
예제 #3
0
        /// <summary>
        /// Lists all processes running on the device.
        /// </summary>
        /// <param name="device">
        /// The device on which to list the processes that are running.
        /// </param>
        /// <param name="client">
        /// A connection to ADB.
        /// </param>
        /// <returns>
        /// An <see cref="IEnumerable{AndroidProcess}"/> that will iterate over all
        /// processes that are currently running on the device.
        /// </returns>
        public static IEnumerable <AndroidProcess> ListProcesses(this DeviceData device, IAdbClient client)
        {
            // There are a couple of gotcha's when listing processes on an Android device.
            // One way would be to run ps and parse the output. However, the output of
            // ps differents from Android version to Android version, is not delimited, nor
            // entirely fixed length, and some of the fields can be empty, so it's almost impossible
            // to parse correctly.
            //
            // The alternative is to directly read the values in /proc/[pid], pretty much like ps
            // does (see https://android.googlesource.com/platform/system/core/+/master/toolbox/ps.c).
            //
            // The easiest way to do the directory listings would be to use the SyncService; unfortunately,
            // the sync service doesn't work very well with /proc/ so we're back to using ls and taking it
            // from there.
            List <AndroidProcess> processes = new List <AndroidProcess>();

            // List all processes by doing ls /proc/.
            // All subfolders which are completely numeric are PIDs

            // Android 7 and above ships with toybox (https://github.com/landley/toybox), which includes
            // an updated ls which behaves slightly different.
            // The -1 parameter is important to make sure each item gets its own line (it's an assumption we
            // make when parsing output); on Android 7 and above we may see things like:
            // 1     135   160   171 ioports      timer_stats
            // 10    13533 16056 172 irq tty
            // 100   136   16066 173 kallsyms uid_cputime
            // but unfortunately older versions do not handle the -1 parameter well. So we need to branch based
            // on the API level. We do the branching on the device (inside a shell script) to avoid roundtrips.
            // This if/then/else syntax was tested on Android 2.x, 4.x and 7
            ConsoleOutputReceiver receiver = new ConsoleOutputReceiver();

            device.ExecuteShellCommand(client, @"SDK=""$(/system/bin/getprop ro.build.version.sdk)""
if [ $SDK -lt 24 ]
then
    /system/bin/ls /proc/
else
    /system/bin/ls -1 /proc/
fi".Replace("\r\n", "\n"), receiver);

            Collection <int> pids = new Collection <int>();

            var output = receiver.ToString();

            using (StringReader reader = new StringReader(output))
            {
                while (reader.Peek() > 0)
                {
                    string line = reader.ReadLine();

                    if (!line.All(c => char.IsDigit(c)))
                    {
                        continue;
                    }

                    var pid = int.Parse(line);

                    pids.Add(pid);
                }
            }

            // For each pid, we can get /proc/[pid]/stat, which contains the process information in a well-defined
            // format - see http://man7.org/linux/man-pages/man5/proc.5.html.
            // Doing cat on each file one by one takes too much time. Doing cat on all of them at the same time doesn't work
            // either, because the command line would be too long.
            // So we do it 25 processes at at time.
            StringBuilder         catBuilder            = new StringBuilder();
            ProcessOutputReceiver processOutputReceiver = new ProcessOutputReceiver();

            catBuilder.Append("cat ");

            for (int i = 0; i < pids.Count; i++)
            {
                catBuilder.Append($"/proc/{pids[i]}/cmdline /proc/{pids[i]}/stat ");

                if (i > 0 && (i % 25 == 0 || i == pids.Count - 1))
                {
                    device.ExecuteShellCommand(client, catBuilder.ToString(), processOutputReceiver);
                    catBuilder.Clear();
                    catBuilder.Append("cat ");
                }
            }

            processOutputReceiver.Flush();

            return(processOutputReceiver.Processes);
        }
예제 #4
0
        public static async Task SendStreaks(string AmountOfStreaks, string StartOfStreak)
        {
            AdbServer         server = new AdbServer();
            StartServerResult Result;

            try
            {
                Result = server.StartServer($"{Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly().Location)}\\adb.exe", restartServerIfNewer: false);

                Console.WriteLine($"Server now running on {AdbClient.AdbServerPort}");
            }
            catch
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Failed to start the server");
                Console.ResetColor();
                return;
            }

            var Devices = AdbClient.Instance.GetDevices();

            if (Devices.Count > 1)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("You cannot have more than 1 phone plugged in");
                Console.ResetColor();
                return;
            }

            Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", $"{Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly().Location)}/Auth.json");
            ImageAnnotatorClient client = ImageAnnotatorClient.Create();

            int StreaksToSend = 0;

            try
            {
                StreaksToSend = int.Parse(AmountOfStreaks);
            }
            catch
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Failed to parse AmountOfStreaks");
                Console.ResetColor();
                return;
            }

            List <string> Names       = new List <string>();
            int           StreaksSent = 0;

            DeviceData Device          = Devices[0];
            var        GetSizeReceiver = new ConsoleOutputReceiver();

            Device.ExecuteShellCommand($"wm size", GetSizeReceiver);
            string[] lines      = GetSizeReceiver.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            string   DeviceSize = lines[1];

            DeviceSize = DeviceSize.Replace("Override size: ", string.Empty);
            string[] Split  = DeviceSize.Split("x");
            string   Width  = Split[0];
            string   Height = Split[1];

            Device.ExecuteShellCommand($"input tap {int.Parse(Width) / 2} {int.Parse(Height) - 150}", GetSizeReceiver);
            Thread.Sleep(150);
            Device.ExecuteShellCommand($"input tap {(int.Parse(Width) / 2) - 50} {int.Parse(Height) - 290}", GetSizeReceiver);
            Thread.Sleep(1200);
            Device.ExecuteShellCommand($"input tap {int.Parse(Width) - 50} {int.Parse(Height) - 100}", GetSizeReceiver);
            Thread.Sleep(500);

            for (int i = 0; i <= 20; i++)
            {
                var    Receiver       = new ConsoleOutputReceiver();
                string RandomFileName = GenerateRandomString(25);

                Device.ExecuteShellCommand($"exec screencap -p > /storage/emulated/0/Pictures/{RandomFileName}.png", Receiver);

                if (string.IsNullOrWhiteSpace(Receiver.ToString()))
                {
                    Console.WriteLine("Screenshot taken");
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(Receiver.ToString());
                    Console.ResetColor();
                    return;
                }

                using (SyncService service = new SyncService(new AdbSocket(new IPEndPoint(IPAddress.Loopback, AdbClient.AdbServerPort)), Device))
                    using (Stream stream = File.OpenWrite(@$ "{Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly().Location)}/Screenshots/{RandomFileName}.png"))
                    {
                        service.Pull($"/storage/emulated/0/Pictures/{RandomFileName}.png", stream, null, CancellationToken.None);
                    }

                Device.ExecuteShellCommand($"rm /storage/emulated/0/Pictures/{RandomFileName}.png", Receiver);
                if (!string.IsNullOrWhiteSpace(Receiver.ToString()))
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Failed to delete screenshot on phone while moving it locally");
                    Console.ResetColor();
                    return;
                }

                var image    = Google.Cloud.Vision.V1.Image.FromFile(@$ "{Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly().Location)}/Screenshots/{RandomFileName}.png");
                var response = client.DetectText(image);

                foreach (var annotation in response)
                {
                    if (annotation != null)
                    {
                        if (annotation.Description.StartsWith(StartOfStreak))
                        {
                            if (annotation.BoundingPoly.Vertices[0].Y <= 2100)
                            {
                                if (!Names.Contains(annotation.Description))
                                {
                                    if (StreaksSent >= StreaksToSend)
                                    {
                                        i = 21;
                                        break;
                                    }
                                    Console.WriteLine(annotation.Description);
                                    Names.Add(annotation.Description);
                                    Device.ExecuteShellCommand($"input tap {annotation.BoundingPoly.Vertices[0].X} {annotation.BoundingPoly.Vertices[0].Y}", Receiver);
                                    StreaksSent++;
                                }
                            }
                        }
                    }
                    Thread.Sleep(50);
                }
                Device.ExecuteShellCommand($"input swipe 250 1100 250 400 300", Receiver);
                Thread.Sleep(950);
            }

            Console.WriteLine("Streaks have been selected, Make sure the application didn't skip any1");
        }