public void ProcessMultiLineOutputTest()
        {
            string content = @"root      1     0     852    628   c1157816 0805d0d6 S /init
            root      2     0     0      0     c10589a4 00000000 S kthreadd
            root      3     2     0      0     c105fd59 00000000 S ksoftirqd/0";

            ProcessOutputReceiver receiver = new ProcessOutputReceiver();

            StringReader reader = new StringReader(content);

            while (reader.Peek() >= 0)
            {
                receiver.AddOutput(reader.ReadLine());
            }

            receiver.Flush();
            Assert.AreEqual(2, receiver.Processes.Count);
        }
        public void ProcessLimitedOutputTest()
        {
            string content = @"  PID USER       VSZ STAT COMMAND
            1 root       340 S    /init
            2 root         0 SW<  [kthreadd]";

            ProcessOutputReceiver receiver = new ProcessOutputReceiver();

            StringReader reader = new StringReader(content);

            while (reader.Peek() >= 0)
            {
                receiver.AddOutput(reader.ReadLine());
            }

            receiver.Flush();
            Assert.AreEqual(2, receiver.Processes.Count);
            Assert.AreEqual("/init", receiver.Processes.First().Name);
            Assert.AreEqual("kthreadd", receiver.Processes.Last().Name);
        }
        /// <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;
        }
Beispiel #4
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>
 /// <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)
 {
     var receiver = new ProcessOutputReceiver();
     device.ExecuteShellCommand("/system/bin/ps", receiver);
     return receiver.Processes;
 }
        public void ProcessOutputTest()
        {
            string output = @"USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
            root      1     0     852    628   c1157816 0805d0d6 S /init
            root      2     0     0      0     c10589a4 00000000 S kthreadd
            root      127   2     0      0     c1052a3b 00000000 S ext4-dio-unwrit
            root      129   1     1572   4     c11850d6 0805f0bb S /sbin/healthd
            shell     145   1     1552   584   c135a860 b7649fe6 S /system/bin/sh
            root      146   1     4764   260   ffffffff 0806ba20 S /sbin/adbd
            system    452   138   511452 44104 ffffffff b765ff1b S system_server
            root      470   2     0      0     c1053187 00000000 S kworker/1:1H
            root      476   1     1544   616   c104b8ee b76b75b6 S /system/bin/sh
            root      478   476   1412   204   c105c979 b771a1e1 S zygotelaunch
            u0_a33    664   138   449648 22100 ffffffff b765ff1b S com.android.music
            u0_a5     698   138   451988 32252 ffffffff b765ff1b S android.process.media
            root      710   1     1312   416   c1157816 b7697fe6 S /system/bin/logwrapper
            root      715   710   1544   612   c104b8ee b76405b6 S /system/bin/sh
            wifi      722   715   5812   2152  c1157816 b74c2610 S /system/bin/wpa_supplicant
            root      731   2     0      0     c1053187 00000000 S kworker/0:1H
            root      754   1     1312   416   c1157816 b7719fe6 S /system/bin/logwrapper
            dhcp      755   754   1624   740   c1157816 b770dfe6 S /system/bin/dhcpcd
            u0_a4     762   138   451852 21908 ffffffff b765ff1b S com.android.dialer
            root      991   146   1556   696   c104b8ee b76345b6 S /system/bin/sh
            root      1044  991   1868   504   00000000 b76c0fe6 R ps";

            ProcessOutputReceiver receiver = new ProcessOutputReceiver();

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

            receiver.Flush();
            Assert.AreEqual(21, receiver.Processes.Count);
            Assert.AreEqual("/init", receiver.Processes.First().Name);
            Assert.AreEqual("ps", receiver.Processes.Last().Name);
        }