Process.java revision d42685d5de1dbd6d75b48d42418f370adaa4daef
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import android.net.LocalSocketAddress;
20import android.net.LocalSocket;
21import android.util.Log;
22import dalvik.system.Zygote;
23
24import java.io.BufferedWriter;
25import java.io.DataInputStream;
26import java.io.IOException;
27import java.io.OutputStreamWriter;
28import java.util.ArrayList;
29
30/*package*/ class ZygoteStartFailedEx extends Exception {
31    /**
32     * Something prevented the zygote process startup from happening normally
33     */
34
35    ZygoteStartFailedEx() {};
36    ZygoteStartFailedEx(String s) {super(s);}
37    ZygoteStartFailedEx(Throwable cause) {super(cause);}
38}
39
40/**
41 * Tools for managing OS processes.
42 */
43public class Process {
44    private static final String LOG_TAG = "Process";
45
46    private static final String ZYGOTE_SOCKET = "zygote";
47
48    /**
49     * Name of a process for running the platform's media services.
50     * {@hide}
51     */
52    public static final String ANDROID_SHARED_MEDIA = "com.android.process.media";
53
54    /**
55     * Name of the process that Google content providers can share.
56     * {@hide}
57     */
58    public static final String GOOGLE_SHARED_APP_CONTENT = "com.google.process.content";
59
60    /**
61     * Defines the UID/GID under which system code runs.
62     */
63    public static final int SYSTEM_UID = 1000;
64
65    /**
66     * Defines the UID/GID under which the telephony code runs.
67     */
68    public static final int PHONE_UID = 1001;
69
70    /**
71     * Defines the UID/GID for the user shell.
72     * @hide
73     */
74    public static final int SHELL_UID = 2000;
75
76    /**
77     * Defines the UID/GID for the log group.
78     * @hide
79     */
80    public static final int LOG_UID = 1007;
81
82    /**
83     * Defines the UID/GID for the WIFI supplicant process.
84     * @hide
85     */
86    public static final int WIFI_UID = 1010;
87
88    /**
89     * Defines the start of a range of UIDs (and GIDs), going from this
90     * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
91     * to applications.
92     */
93    public static final int FIRST_APPLICATION_UID = 10000;
94    /**
95     * Last of application-specific UIDs starting at
96     * {@link #FIRST_APPLICATION_UID}.
97     */
98    public static final int LAST_APPLICATION_UID = 99999;
99
100    /**
101     * Defines a secondary group id for access to the bluetooth hardware.
102     */
103    public static final int BLUETOOTH_GID = 2000;
104
105    /**
106     * Standard priority of application threads.
107     * Use with {@link #setThreadPriority(int)} and
108     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
109     * {@link java.lang.Thread} class.
110     */
111    public static final int THREAD_PRIORITY_DEFAULT = 0;
112
113    /*
114     * ***************************************
115     * ** Keep in sync with utils/threads.h **
116     * ***************************************
117     */
118
119    /**
120     * Lowest available thread priority.  Only for those who really, really
121     * don't want to run if anything else is happening.
122     * Use with {@link #setThreadPriority(int)} and
123     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
124     * {@link java.lang.Thread} class.
125     */
126    public static final int THREAD_PRIORITY_LOWEST = 19;
127
128    /**
129     * Standard priority background threads.  This gives your thread a slightly
130     * lower than normal priority, so that it will have less chance of impacting
131     * the responsiveness of the user interface.
132     * Use with {@link #setThreadPriority(int)} and
133     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
134     * {@link java.lang.Thread} class.
135     */
136    public static final int THREAD_PRIORITY_BACKGROUND = 10;
137
138    /**
139     * Standard priority of threads that are currently running a user interface
140     * that the user is interacting with.  Applications can not normally
141     * change to this priority; the system will automatically adjust your
142     * application threads as the user moves through the UI.
143     * Use with {@link #setThreadPriority(int)} and
144     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
145     * {@link java.lang.Thread} class.
146     */
147    public static final int THREAD_PRIORITY_FOREGROUND = -2;
148
149    /**
150     * Standard priority of system display threads, involved in updating
151     * the user interface.  Applications can not
152     * normally change to this priority.
153     * Use with {@link #setThreadPriority(int)} and
154     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
155     * {@link java.lang.Thread} class.
156     */
157    public static final int THREAD_PRIORITY_DISPLAY = -4;
158
159    /**
160     * Standard priority of the most important display threads, for compositing
161     * the screen and retrieving input events.  Applications can not normally
162     * change to this priority.
163     * Use with {@link #setThreadPriority(int)} and
164     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
165     * {@link java.lang.Thread} class.
166     */
167    public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;
168
169    /**
170     * Standard priority of audio threads.  Applications can not normally
171     * change to this priority.
172     * Use with {@link #setThreadPriority(int)} and
173     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
174     * {@link java.lang.Thread} class.
175     */
176    public static final int THREAD_PRIORITY_AUDIO = -16;
177
178    /**
179     * Standard priority of the most important audio threads.
180     * Applications can not normally change to this priority.
181     * Use with {@link #setThreadPriority(int)} and
182     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
183     * {@link java.lang.Thread} class.
184     */
185    public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;
186
187    /**
188     * Minimum increment to make a priority more favorable.
189     */
190    public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1;
191
192    /**
193     * Minimum increment to make a priority less favorable.
194     */
195    public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;
196
197    /**
198     * Default thread group - gets a 'normal' share of the CPU
199     * @hide
200     */
201    public static final int THREAD_GROUP_DEFAULT = 0;
202
203    /**
204     * Background non-interactive thread group - All threads in
205     * this group are scheduled with a reduced share of the CPU.
206     * @hide
207     */
208    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 1;
209
210    /**
211     * Foreground 'boost' thread group - All threads in
212     * this group are scheduled with an increased share of the CPU
213     * @hide
214     **/
215    public static final int THREAD_GROUP_FG_BOOST = 2;
216
217    public static final int SIGNAL_QUIT = 3;
218    public static final int SIGNAL_KILL = 9;
219    public static final int SIGNAL_USR1 = 10;
220
221    // State for communicating with zygote process
222
223    static LocalSocket sZygoteSocket;
224    static DataInputStream sZygoteInputStream;
225    static BufferedWriter sZygoteWriter;
226
227    /** true if previous zygote open failed */
228    static boolean sPreviousZygoteOpenFailed;
229
230    /**
231     * Start a new process.
232     *
233     * <p>If processes are enabled, a new process is created and the
234     * static main() function of a <var>processClass</var> is executed there.
235     * The process will continue running after this function returns.
236     *
237     * <p>If processes are not enabled, a new thread in the caller's
238     * process is created and main() of <var>processClass</var> called there.
239     *
240     * <p>The niceName parameter, if not an empty string, is a custom name to
241     * give to the process instead of using processClass.  This allows you to
242     * make easily identifyable processes even if you are using the same base
243     * <var>processClass</var> to start them.
244     *
245     * @param processClass The class to use as the process's main entry
246     *                     point.
247     * @param niceName A more readable name to use for the process.
248     * @param uid The user-id under which the process will run.
249     * @param gid The group-id under which the process will run.
250     * @param gids Additional group-ids associated with the process.
251     * @param enableDebugger True if debugging should be enabled for this process.
252     * @param zygoteArgs Additional arguments to supply to the zygote process.
253     *
254     * @return int If > 0 the pid of the new process; if 0 the process is
255     *         being emulated by a thread
256     * @throws RuntimeException on fatal start failure
257     *
258     * {@hide}
259     */
260    public static final int start(final String processClass,
261                                  final String niceName,
262                                  int uid, int gid, int[] gids,
263                                  int debugFlags,
264                                  String[] zygoteArgs)
265    {
266        if (supportsProcesses()) {
267            try {
268                return startViaZygote(processClass, niceName, uid, gid, gids,
269                        debugFlags, zygoteArgs);
270            } catch (ZygoteStartFailedEx ex) {
271                Log.e(LOG_TAG,
272                        "Starting VM process through Zygote failed");
273                throw new RuntimeException(
274                        "Starting VM process through Zygote failed", ex);
275            }
276        } else {
277            // Running in single-process mode
278
279            Runnable runnable = new Runnable() {
280                        public void run() {
281                            Process.invokeStaticMain(processClass);
282                        }
283            };
284
285            // Thread constructors must not be called with null names (see spec).
286            if (niceName != null) {
287                new Thread(runnable, niceName).start();
288            } else {
289                new Thread(runnable).start();
290            }
291
292            return 0;
293        }
294    }
295
296    /**
297     * Start a new process.  Don't supply a custom nice name.
298     * {@hide}
299     */
300    public static final int start(String processClass, int uid, int gid,
301            int[] gids, int debugFlags, String[] zygoteArgs) {
302        return start(processClass, "", uid, gid, gids,
303                debugFlags, zygoteArgs);
304    }
305
306    private static void invokeStaticMain(String className) {
307        Class cl;
308        Object args[] = new Object[1];
309
310        args[0] = new String[0];     //this is argv
311
312        try {
313            cl = Class.forName(className);
314            cl.getMethod("main", new Class[] { String[].class })
315                    .invoke(null, args);
316        } catch (Exception ex) {
317            // can be: ClassNotFoundException,
318            // NoSuchMethodException, SecurityException,
319            // IllegalAccessException, IllegalArgumentException
320            // InvocationTargetException
321            // or uncaught exception from main()
322
323            Log.e(LOG_TAG, "Exception invoking static main on "
324                    + className, ex);
325
326            throw new RuntimeException(ex);
327        }
328
329    }
330
331    /** retry interval for opening a zygote socket */
332    static final int ZYGOTE_RETRY_MILLIS = 500;
333
334    /**
335     * Tries to open socket to Zygote process if not already open. If
336     * already open, does nothing.  May block and retry.
337     */
338    private static void openZygoteSocketIfNeeded()
339            throws ZygoteStartFailedEx {
340
341        int retryCount;
342
343        if (sPreviousZygoteOpenFailed) {
344            /*
345             * If we've failed before, expect that we'll fail again and
346             * don't pause for retries.
347             */
348            retryCount = 0;
349        } else {
350            retryCount = 10;
351        }
352
353        /*
354         * See bug #811181: Sometimes runtime can make it up before zygote.
355         * Really, we'd like to do something better to avoid this condition,
356         * but for now just wait a bit...
357         */
358        for (int retry = 0
359                ; (sZygoteSocket == null) && (retry < (retryCount + 1))
360                ; retry++ ) {
361
362            if (retry > 0) {
363                try {
364                    Log.i("Zygote", "Zygote not up yet, sleeping...");
365                    Thread.sleep(ZYGOTE_RETRY_MILLIS);
366                } catch (InterruptedException ex) {
367                    // should never happen
368                }
369            }
370
371            try {
372                sZygoteSocket = new LocalSocket();
373
374                sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
375                        LocalSocketAddress.Namespace.RESERVED));
376
377                sZygoteInputStream
378                        = new DataInputStream(sZygoteSocket.getInputStream());
379
380                sZygoteWriter =
381                    new BufferedWriter(
382                            new OutputStreamWriter(
383                                    sZygoteSocket.getOutputStream()),
384                            256);
385
386                Log.i("Zygote", "Process: zygote socket opened");
387
388                sPreviousZygoteOpenFailed = false;
389                break;
390            } catch (IOException ex) {
391                if (sZygoteSocket != null) {
392                    try {
393                        sZygoteSocket.close();
394                    } catch (IOException ex2) {
395                        Log.e(LOG_TAG,"I/O exception on close after exception",
396                                ex2);
397                    }
398                }
399
400                sZygoteSocket = null;
401            }
402        }
403
404        if (sZygoteSocket == null) {
405            sPreviousZygoteOpenFailed = true;
406            throw new ZygoteStartFailedEx("connect failed");
407        }
408    }
409
410    /**
411     * Sends an argument list to the zygote process, which starts a new child
412     * and returns the child's pid. Please note: the present implementation
413     * replaces newlines in the argument list with spaces.
414     * @param args argument list
415     * @return PID of new child process
416     * @throws ZygoteStartFailedEx if process start failed for any reason
417     */
418    private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
419            throws ZygoteStartFailedEx {
420
421        int pid;
422
423        openZygoteSocketIfNeeded();
424
425        try {
426            /**
427             * See com.android.internal.os.ZygoteInit.readArgumentList()
428             * Presently the wire format to the zygote process is:
429             * a) a count of arguments (argc, in essence)
430             * b) a number of newline-separated argument strings equal to count
431             *
432             * After the zygote process reads these it will write the pid of
433             * the child or -1 on failure.
434             */
435
436            sZygoteWriter.write(Integer.toString(args.size()));
437            sZygoteWriter.newLine();
438
439            int sz = args.size();
440            for (int i = 0; i < sz; i++) {
441                String arg = args.get(i);
442                if (arg.indexOf('\n') >= 0) {
443                    throw new ZygoteStartFailedEx(
444                            "embedded newlines not allowed");
445                }
446                sZygoteWriter.write(arg);
447                sZygoteWriter.newLine();
448            }
449
450            sZygoteWriter.flush();
451
452            // Should there be a timeout on this?
453            pid = sZygoteInputStream.readInt();
454
455            if (pid < 0) {
456                throw new ZygoteStartFailedEx("fork() failed");
457            }
458        } catch (IOException ex) {
459            try {
460                if (sZygoteSocket != null) {
461                    sZygoteSocket.close();
462                }
463            } catch (IOException ex2) {
464                // we're going to fail anyway
465                Log.e(LOG_TAG,"I/O exception on routine close", ex2);
466            }
467
468            sZygoteSocket = null;
469
470            throw new ZygoteStartFailedEx(ex);
471        }
472
473        return pid;
474    }
475
476    /**
477     * Starts a new process via the zygote mechanism.
478     *
479     * @param processClass Class name whose static main() to run
480     * @param niceName 'nice' process name to appear in ps
481     * @param uid a POSIX uid that the new process should setuid() to
482     * @param gid a POSIX gid that the new process shuold setgid() to
483     * @param gids null-ok; a list of supplementary group IDs that the
484     * new process should setgroup() to.
485     * @param enableDebugger True if debugging should be enabled for this process.
486     * @param extraArgs Additional arguments to supply to the zygote process.
487     * @return PID
488     * @throws ZygoteStartFailedEx if process start failed for any reason
489     */
490    private static int startViaZygote(final String processClass,
491                                  final String niceName,
492                                  final int uid, final int gid,
493                                  final int[] gids,
494                                  int debugFlags,
495                                  String[] extraArgs)
496                                  throws ZygoteStartFailedEx {
497        int pid;
498
499        synchronized(Process.class) {
500            ArrayList<String> argsForZygote = new ArrayList<String>();
501
502            // --runtime-init, --setuid=, --setgid=,
503            // and --setgroups= must go first
504            argsForZygote.add("--runtime-init");
505            argsForZygote.add("--setuid=" + uid);
506            argsForZygote.add("--setgid=" + gid);
507            if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
508                argsForZygote.add("--enable-debugger");
509            }
510            if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
511                argsForZygote.add("--enable-checkjni");
512            }
513            if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
514                argsForZygote.add("--enable-assert");
515            }
516
517            //TODO optionally enable debuger
518            //argsForZygote.add("--enable-debugger");
519
520            // --setgroups is a comma-separated list
521            if (gids != null && gids.length > 0) {
522                StringBuilder sb = new StringBuilder();
523                sb.append("--setgroups=");
524
525                int sz = gids.length;
526                for (int i = 0; i < sz; i++) {
527                    if (i != 0) {
528                        sb.append(',');
529                    }
530                    sb.append(gids[i]);
531                }
532
533                argsForZygote.add(sb.toString());
534            }
535
536            if (niceName != null) {
537                argsForZygote.add("--nice-name=" + niceName);
538            }
539
540            argsForZygote.add(processClass);
541
542            if (extraArgs != null) {
543                for (String arg : extraArgs) {
544                    argsForZygote.add(arg);
545                }
546            }
547
548            pid = zygoteSendArgsAndGetPid(argsForZygote);
549        }
550
551        if (pid <= 0) {
552            throw new ZygoteStartFailedEx("zygote start failed:" + pid);
553        }
554
555        return pid;
556    }
557
558    /**
559     * Returns elapsed milliseconds of the time this process has run.
560     * @return  Returns the number of milliseconds this process has return.
561     */
562    public static final native long getElapsedCpuTime();
563
564    /**
565     * Returns the identifier of this process, which can be used with
566     * {@link #killProcess} and {@link #sendSignal}.
567     */
568    public static final native int myPid();
569
570    /**
571     * Returns the identifier of the calling thread, which be used with
572     * {@link #setThreadPriority(int, int)}.
573     */
574    public static final native int myTid();
575
576    /**
577     * Returns the identifier of this process's user.
578     */
579    public static final native int myUid();
580
581    /**
582     * Returns the UID assigned to a particular user name, or -1 if there is
583     * none.  If the given string consists of only numbers, it is converted
584     * directly to a uid.
585     */
586    public static final native int getUidForName(String name);
587
588    /**
589     * Returns the GID assigned to a particular user name, or -1 if there is
590     * none.  If the given string consists of only numbers, it is converted
591     * directly to a gid.
592     */
593    public static final native int getGidForName(String name);
594
595    /**
596     * Returns a uid for a currently running process.
597     * @param pid the process id
598     * @return the uid of the process, or -1 if the process is not running.
599     * @hide pending API council review
600     */
601    public static final int getUidForPid(int pid) {
602        String[] procStatusLabels = { "Uid:" };
603        long[] procStatusValues = new long[1];
604        procStatusValues[0] = -1;
605        Process.readProcLines("/proc/" + pid + "/status", procStatusLabels, procStatusValues);
606        return (int) procStatusValues[0];
607    }
608
609    /**
610     * Set the priority of a thread, based on Linux priorities.
611     *
612     * @param tid The identifier of the thread/process to change.
613     * @param priority A Linux priority level, from -20 for highest scheduling
614     * priority to 19 for lowest scheduling priority.
615     *
616     * @throws IllegalArgumentException Throws IllegalArgumentException if
617     * <var>tid</var> does not exist.
618     * @throws SecurityException Throws SecurityException if your process does
619     * not have permission to modify the given thread, or to use the given
620     * priority.
621     */
622    public static final native void setThreadPriority(int tid, int priority)
623            throws IllegalArgumentException, SecurityException;
624
625    /**
626     * Sets the scheduling group for a thread.
627     * @hide
628     * @param tid The indentifier of the thread/process to change.
629     * @param group The target group for this thread/process.
630     *
631     * @throws IllegalArgumentException Throws IllegalArgumentException if
632     * <var>tid</var> does not exist.
633     * @throws SecurityException Throws SecurityException if your process does
634     * not have permission to modify the given thread, or to use the given
635     * priority.
636     */
637    public static final native void setThreadGroup(int tid, int group)
638            throws IllegalArgumentException, SecurityException;
639    /**
640     * Sets the scheduling group for a process and all child threads
641     * @hide
642     * @param pid The indentifier of the process to change.
643     * @param group The target group for this process.
644     *
645     * @throws IllegalArgumentException Throws IllegalArgumentException if
646     * <var>tid</var> does not exist.
647     * @throws SecurityException Throws SecurityException if your process does
648     * not have permission to modify the given thread, or to use the given
649     * priority.
650     */
651    public static final native void setProcessGroup(int pid, int group)
652            throws IllegalArgumentException, SecurityException;
653
654    /**
655     * Set the priority of the calling thread, based on Linux priorities.  See
656     * {@link #setThreadPriority(int, int)} for more information.
657     *
658     * @param priority A Linux priority level, from -20 for highest scheduling
659     * priority to 19 for lowest scheduling priority.
660     *
661     * @throws IllegalArgumentException Throws IllegalArgumentException if
662     * <var>tid</var> does not exist.
663     * @throws SecurityException Throws SecurityException if your process does
664     * not have permission to modify the given thread, or to use the given
665     * priority.
666     *
667     * @see #setThreadPriority(int, int)
668     */
669    public static final native void setThreadPriority(int priority)
670            throws IllegalArgumentException, SecurityException;
671
672    /**
673     * Return the current priority of a thread, based on Linux priorities.
674     *
675     * @param tid The identifier of the thread/process to change.
676     *
677     * @return Returns the current priority, as a Linux priority level,
678     * from -20 for highest scheduling priority to 19 for lowest scheduling
679     * priority.
680     *
681     * @throws IllegalArgumentException Throws IllegalArgumentException if
682     * <var>tid</var> does not exist.
683     */
684    public static final native int getThreadPriority(int tid)
685            throws IllegalArgumentException;
686
687    /**
688     * Determine whether the current environment supports multiple processes.
689     *
690     * @return Returns true if the system can run in multiple processes, else
691     * false if everything is running in a single process.
692     */
693    public static final native boolean supportsProcesses();
694
695    /**
696     * Set the out-of-memory badness adjustment for a process.
697     *
698     * @param pid The process identifier to set.
699     * @param amt Adjustment value -- linux allows -16 to +15.
700     *
701     * @return Returns true if the underlying system supports this
702     *         feature, else false.
703     *
704     * {@hide}
705     */
706    public static final native boolean setOomAdj(int pid, int amt);
707
708    /**
709     * Change this process's argv[0] parameter.  This can be useful to show
710     * more descriptive information in things like the 'ps' command.
711     *
712     * @param text The new name of this process.
713     *
714     * {@hide}
715     */
716    public static final native void setArgV0(String text);
717
718    /**
719     * Kill the process with the given PID.
720     * Note that, though this API allows us to request to
721     * kill any process based on its PID, the kernel will
722     * still impose standard restrictions on which PIDs you
723     * are actually able to kill.  Typically this means only
724     * the process running the caller's packages/application
725     * and any additional processes created by that app; packages
726     * sharing a common UID will also be able to kill each
727     * other's processes.
728     */
729    public static final void killProcess(int pid) {
730        sendSignal(pid, SIGNAL_KILL);
731    }
732
733    /** @hide */
734    public static final native int setUid(int uid);
735
736    /** @hide */
737    public static final native int setGid(int uid);
738
739    /**
740     * Send a signal to the given process.
741     *
742     * @param pid The pid of the target process.
743     * @param signal The signal to send.
744     */
745    public static final native void sendSignal(int pid, int signal);
746
747    /** @hide */
748    public static final native long getFreeMemory();
749
750    /** @hide */
751    public static final native void readProcLines(String path,
752            String[] reqFields, long[] outSizes);
753
754    /** @hide */
755    public static final native int[] getPids(String path, int[] lastArray);
756
757    /** @hide */
758    public static final int PROC_TERM_MASK = 0xff;
759    /** @hide */
760    public static final int PROC_ZERO_TERM = 0;
761    /** @hide */
762    public static final int PROC_SPACE_TERM = (int)' ';
763    /** @hide */
764    public static final int PROC_TAB_TERM = (int)'\t';
765    /** @hide */
766    public static final int PROC_COMBINE = 0x100;
767    /** @hide */
768    public static final int PROC_PARENS = 0x200;
769    /** @hide */
770    public static final int PROC_OUT_STRING = 0x1000;
771    /** @hide */
772    public static final int PROC_OUT_LONG = 0x2000;
773    /** @hide */
774    public static final int PROC_OUT_FLOAT = 0x4000;
775
776    /** @hide */
777    public static final native boolean readProcFile(String file, int[] format,
778            String[] outStrings, long[] outLongs, float[] outFloats);
779
780    /** @hide */
781    public static final native boolean parseProcLine(byte[] buffer, int startIndex,
782            int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats);
783
784    /**
785     * Gets the total Pss value for a given process, in bytes.
786     *
787     * @param pid the process to the Pss for
788     * @return the total Pss value for the given process in bytes,
789     *  or -1 if the value cannot be determined
790     * @hide
791     */
792    public static final native long getPss(int pid);
793}
794