From 33e499ea364e4e061964bc8fe16365fd632eb39d Mon Sep 17 00:00:00 2001
From: Scott Main Figure 1. An ANR dialog displayed to the user. It's possible to write code that wins every performance test in the world,
+but still feels sluggish, hang or freeze for significant periods, or take too
+long to process input. The worst thing that can happen to your app's responsiveness
+is an "Application Not Responding" (ANR) dialog. In Android, the system guards against applications that are insufficiently
+responsive for a period of time by displaying a dialog that says your app has
+stopped responding, such as the dialog
+in Figure 1. At this point, your app has been unresponsive for a considerable
+period of time so the system offers the user an option to quit the app. It's critical
+to design responsiveness into your application so the system never displays
+an ANR dialog to the user. This document describes how the Android system determines whether an
+application is not responding and provides guidelines for ensuring that your
+application stays responsive. Generally, the system displays an ANR if an application cannot respond to
+user input. For example, if an application blocks on some I/O operation
+(frequently a network access) on the UI thread so the system can't
+process incoming user input events. Or perhaps the app
+spends too much time building an elaborate in-memory
+structure or computing the next move in a game on the UI thread. It's always important to make
+sure these computations are efficient, but even the
+most efficient code still takes time to run. In any situation in which your app performs a potentially lengthy operation,
+you should not perform the work on the UI thread, but instead create a
+worker thread and do most of the work there. This keeps the UI thread (which drives the user
+interface event loop) running and prevents the system from concluding that your code
+has frozen. Because such threading usually is accomplished at the class
+level, you can think of responsiveness as a class problem. (Compare
+this with basic code performance, which is a method-level
+concern.) In Android, application responsiveness is monitored by the Activity Manager
+and Window Manager system services. Android will display the ANR dialog
+for a particular application when it detects one of the following
+conditions: Android applications normally run entirely on a single thread by default
+the "UI thread" or "main thread").
+This means anything your application is doing in the UI thread that
+takes a long time to complete can trigger the ANR dialog because your
+application is not giving itself a chance to handle the input event or intent
+broadcasts. Therefore, any method that runs in the UI thread should do as little work
+as possible on that thread. In particular, activities should do as little as possible to set
+up in key life-cycle methods such as {@link android.app.Activity#onCreate onCreate()}
+and {@link android.app.Activity#onResume onResume()}.
+Potentially long running operations such as network
+or database operations, or computationally expensive calculations such as
+resizing bitmaps should be done in a worker thread (or in the case of databases
+operations, via an asynchronous request). The most effecive way to create a worker thread for longer
+operations is with the {@link android.os.AsyncTask}
+class. Simply extend {@link android.os.AsyncTask} and implement the
+{@link android.os.AsyncTask#doInBackground doInBackground()} method to perform the work.
+To post progress changes to the user, you can call
+ {@link android.os.AsyncTask#publishProgress publishProgress()}, which invokes the
+ {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} callback method. From your
+ implementation of {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} (which
+ runs on the UI thread), you can notify the user. For example: To execute this worker thread, simply create an instance and
+ call {@link android.os.AsyncTask#execute execute()}: Although it's more complicated than {@link android.os.AsyncTask}, you might want to instead
+create your own {@link java.lang.Thread} or {@link android.os.HandlerThread} class. If you do,
+you should set the thread priority to "background" priority by calling {@link
+android.os.Process#setThreadPriority Process.setThreadPriority()} and passing {@link
+android.os.Process#THREAD_PRIORITY_BACKGROUND}. If you don't set the thread to a lower priority
+this way, then the thread could still slow down your app because it operates at the same priority
+as the UI thread by default. If you implement {@link java.lang.Thread} or {@link android.os.HandlerThread},
+be sure that your UI thread does not block while waiting for the worker thread to
+complete—do not call {@link java.lang.Thread#wait Thread.wait()} or
+{@link java.lang.Thread#sleep Thread.sleep()}. Instead of blocking while waiting for a worker
+thread to complete, your main thread should provide a {@link
+android.os.Handler} for the other threads to post back to upon completion.
+Designing your application in this way will allow your app's UI thread to remain
+responsive to input and thus avoid ANR dialogs caused by the 5 second input
+event timeout. The specific constraint on {@link android.content.BroadcastReceiver} execution time
+emphasizes what broadcast receivers are meant to do:
+small, discrete amounts of work in the background such
+as saving a setting or registering a {@link android.app.Notification}. So as with other methods
+called in the UI thread, applications should avoid potentially long-running
+operations or calculations in a broadcast receiver. But instead of doing intensive
+tasks via worker threads, your
+application should start an {@link android.app.IntentService} if a
+potentially long running action needs to be taken in response to an intent
+broadcast. Tip:
+You can use {@link android.os.StrictMode} to help find potentially
+long running operations such as network or database operations that
+you might accidentally be doing your main thread. Generally, 100 to 200ms is the threshold beyond which users will perceive
+slowness in an application. As such, here
+are some additional tips beyond what you should do to avoid ANR and
+make your application seem responsive to users: JNI is the Java Native Interface. It defines a way for managed code
+(written in the Java programming language) to interact with native
+code (written in C/C++). It's vendor-neutral, has support for loading code from
+dynamic shared libraries, and while cumbersome at times is reasonably efficient. You really should read through the
+JNI spec for J2SE 6
+to get a sense for how JNI works and what features are available. Some
+aspects of the interface aren't immediately obvious on
+first reading, so you may find the next few sections handy.
+There's a more detailed JNI Programmer's Guide and Specification. JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially
+pointers to pointers to function tables. (In the C++ version, they're classes with a
+pointer to a function table and a member function for each JNI function that indirects through
+the table.) The JavaVM provides the "invocation interface" functions,
+which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process,
+but Android only allows one. The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as
+the first argument. The JNIEnv is used for thread-local storage. For this reason, you cannot share a JNIEnv between threads.
+If a piece of code has no other way to get its JNIEnv, you should share
+the JavaVM, and use The C declarations of JNIEnv and JavaVM are different from the C++
+declarations. The All threads are Linux threads, scheduled by the kernel. They're usually
+started from managed code (using Attaching a natively-created thread causes a Android does not suspend threads executing native code. If
+garbage collection is in progress, or the debugger has issued a suspend
+request, Android will pause the thread the next time it makes a JNI call. Threads attached through JNI must call
+ If you want to access an object's field from native code, you would do the following: Similarly, to call a method, you'd first get a class object reference and then a method ID. The IDs are often just
+pointers to internal runtime data structures. Looking them up may require several string
+comparisons, but once you have them the actual call to get the field or invoke the method
+is very quick. If performance is important, it's useful to look the values up once and cache the results
+in your native code. Because there is a limit of one JavaVM per process, it's reasonable
+to store this data in a static local structure. The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes
+are only unloaded if all classes associated with a ClassLoader can be garbage collected,
+which is rare but will not be impossible in Android. Note however that
+the If you would like to cache the IDs when a class is loaded, and automatically re-cache them
+if the class is ever unloaded and reloaded, the correct way to initialize
+the IDs is to add a piece of code that looks like this to the appropriate class: Create a Every argument passed to a native method, and almost every object returned
+by a JNI function is a "local reference". This means that it's valid for the
+duration of the current native method in the current thread.
+Even if the object itself continues to live on after the native method
+returns, the reference is not valid.
+ This applies to all sub-classes of The only way to get non-local references is via the functions
+ If you want to hold on to a reference for a longer period, you must use
+a "global" reference. The This pattern is commonly used when caching a jclass returned
+from All JNI methods accept both local and global references as arguments.
+It's possible for references to the same object to have different values.
+For example, the return values from consecutive calls to
+ One consequence of this is that you
+must not assume object references are constant or unique
+in native code. The 32-bit value representing an object may be different
+from one invocation of a method to the next, and it's possible that two
+different objects could have the same 32-bit value on consecutive calls. Do
+not use Programmers are required to "not excessively allocate" local references. In practical terms this means
+that if you're creating large numbers of local references, perhaps while running through an array of
+objects, you should free them manually with
+ Note that One unusual case deserves separate mention. If you attach a native
+thread with The Java programming language uses UTF-16. For convenience, JNI provides methods that work with Modified UTF-8 as well. The
+modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00.
+The nice thing about this is that you can count on having C-style zero-terminated strings,
+suitable for use with standard libc string functions. The down side is that you cannot pass
+arbitrary UTF-8 data to JNI and expect it to work correctly. If possible, it's usually faster to operate with UTF-16 strings. Android
+currently does not require a copy in Don't forget to Data passed to NewStringUTF must be in Modified UTF-8 format. A
+common mistake is reading character data from a file or network stream
+and handing it to JNI provides functions for accessing the contents of array objects.
+While arrays of objects must be accessed one entry at a time, arrays of
+primitives can be read and written directly as if they were declared in C. To make the interface as efficient as possible without constraining
+the VM implementation, the You can determine whether or not the data was copied by passing in a
+non-NULL pointer for the The One reason for checking the It is a common mistake (repeated in example code) to assume that you can skip the Also note that the There is an alternative to calls like This grabs the array, copies the first One can accomplish the same thing more simply: This has several advantages: Similarly, you can use the You must not call most JNI functions while an exception is pending.
+Your code is expected to notice the exception (via the function's return value,
+ The only JNI functions that you are allowed to call while an exception is
+pending are: Many JNI calls can throw an exception, but often provide a simpler way
+of checking for failure. For example, if Note that exceptions thrown by interpreted code do not unwind native stack
+frames, and Android does not yet support C++ exceptions.
+The JNI Native code can "catch" an exception by calling There are no built-in functions for manipulating the JNI does very little error checking. Errors usually result in a crash. Android also offers a mode called CheckJNI, where the JavaVM and JNIEnv function table pointers are switched to tables of functions that perform an extended series of checks before calling the standard implementation. The additional checks include: (Accessibility of methods and fields is still not checked: access restrictions don't apply to native code.) There are several ways to enable CheckJNI. If you’re using the emulator, CheckJNI is on by default. If you have a rooted device, you can use the following sequence of commands to restart the runtime with CheckJNI enabled: In either of these cases, you’ll see something like this in your logcat output when the runtime starts: If you have a regular device, you can use the following command: This won’t affect already-running apps, but any app launched from that point on will have CheckJNI enabled. (Change the property to any other value or simply rebooting will disable CheckJNI again.) In this case, you’ll see something like this in your logcat output the next time an app starts: You can load native code from shared libraries with the standard
+ The You can also call This is the recommended approach, but not the only approach. Explicit
+registration is not required, nor is it necessary that you provide a
+ One other note about Android is currently expected to run on 32-bit platforms. In theory it
+could be built for a 64-bit system, but that is not a goal at this time.
+For the most part this isn't something that you will need to worry about
+when interacting with native code,
+but it becomes significant if you plan to store pointers to native
+structures in integer fields in an object. To support architectures
+that use 64-bit pointers, you need to stash your native pointers in a
+ All JNI 1.6 features are supported, with the following exception: For backward compatibility with older Android releases, you may need to
+be aware of: Until Android 2.0 (Eclair), the '$' character was not properly
+ converted to "_00024" during searches for method names. Working
+ around this requires using explicit registration or moving the
+ native methods out of inner classes.
+ Until Android 2.0 (Eclair), it was not possible to use a Until Android 2.2 (Froyo), weak global references were not implemented.
+ Older versions will vigorously reject attempts to use them. You can use
+ the Android platform version constants to test for support.
+ Until Android 4.0 (Ice Cream Sandwich), weak global references could only
+ be passed to From Android 4.0 (Ice Cream Sandwich) on, weak global references can be
+ used like any other JNI references. Until Android 4.0 (Ice Cream Sandwich), local references were
+ actually direct pointers. Ice Cream Sandwich added the indirection
+ necessary to support better garbage collectors, but this means that lots
+ of JNI bugs are undetectable on older releases. See
+ JNI Local Reference Changes in ICS for more details.
+ Until Android 4.0 (Ice Cream Sandwich), as a consequence of the use of
+ direct pointers (see above), it was impossible to implement
+ When working on native code it's not uncommon to see a failure like this: In some cases it means what it says — the library wasn't found. In
+other cases the library exists but couldn't be opened by Common reasons why you might encounter "library not found" exceptions: Another class of In logcat, you'll see: This means that the runtime tried to find a matching method but was
+unsuccessful. Some common reasons for this are: Using Make sure that the class name string has the correct format. JNI class
+names start with the package name and are separated with slashes,
+such as If the class name looks right, you could be running into a class loader
+issue. The topmost method is This usually does what you want. You can get into trouble if you
+create a thread yourself (perhaps by calling The topmost method is There are a few ways to work around this: You may find yourself in a situation where you need to access a large
+buffer of raw data from both managed and native code. Common examples
+include manipulation of bitmaps or sound samples. There are two
+basic approaches. You can store the data in a The alternative is to store the data in a direct byte buffer. These
+can be created with The choice of which to use depends on two factors: If there's no clear winner, use a direct byte buffer. Support for them
+is built directly into JNI, and performance should improve in future releases. This document primarily covers micro-optimizations that can improve overall app performance
+when combined, but it's unlikely that these changes will result in dramatic
+performance effects. Choosing the right algorithms and data structures should always be your
+priority, but is outside the scope of this document. You should use the tips in this document
+as general coding practices that you can incorporate into your habits for general code
+efficiency. There are two basic rules for writing efficient code: One of the trickiest problems you'll face when micro-optimizing an Android
+app is that your app is certain to be running on multiple types of
+hardware. Different versions of the VM running on different
+processors running at different speeds. It's not even generally the case
+that you can simply say "device X is a factor F faster/slower than device Y",
+and scale your results from one device to others. In particular, measurement
+on the emulator tells you very little about performance on any device. There
+are also huge differences between devices with and without a
+JIT: the best
+code for a device with a JIT is not always the best code for a device
+without. To ensure your app performs well across a wide variety of devices, ensure
+your code is efficient at all levels and agressively optimize your performance. Object creation is never free. A generational garbage collector with per-thread allocation
+pools for temporary objects can make allocation cheaper, but allocating memory
+is always more expensive than not allocating memory. As you allocate more objects in your app, you will force a periodic
+garbage collection, creating little "hiccups" in the user experience. The
+concurrent garbage collector introduced in Android 2.3 helps, but unnecessary work
+should always be avoided. Thus, you should avoid creating object instances you don't need to. Some
+examples of things that can help: A somewhat more radical idea is to slice up multidimensional arrays into
+parallel single one-dimension arrays: Generally speaking, avoid creating short-term temporary objects if you
+can. Fewer objects created mean less-frequent garbage collection, which has
+a direct impact on user experience. If you don't need to access an object's fields, make your method static.
+Invocations will be about 15%-20% faster.
+It's also good practice, because you can tell from the method
+signature that calling the method can't alter the object's state. Consider the following declaration at the top of a class: The compiler generates a class initializer method, called
+ We can improve matters with the "final" keyword: The class no longer requires a Note: This optimization applies only to primitive types and
+{@link java.lang.String} constants, not arbitrary reference types. Still, it's good
+practice to declare constants In native languages like C++ it's common practice to use getters
+( However, this is a bad idea on Android. Virtual method calls are expensive,
+much more so than instance field lookups. It's reasonable to follow
+common object-oriented programming practices and have getters and setters
+in the public interface, but within a class you should always access
+fields directly. Without a JIT,
+direct field access is about 3x faster than invoking a
+trivial getter. With the JIT (where direct field access is as cheap as
+accessing a local), direct field access is about 7x faster than invoking a
+trivial getter. Note that if you're using ProGuard,
+you can have the best of both worlds because ProGuard can inline accessors for you. The enhanced There are several alternatives for iterating through an array: So, you should use the enhanced Tip:
+Also see Josh Bloch's Effective Java, item 46. Consider the following class definition: What's important here is that we define a private inner class
+( The problem is that the VM considers direct access to The inner class code calls these static methods whenever it needs to
+access the If you're using code like this in a performance hotspot, you can avoid the
+overhead by declaring fields and methods accessed by inner classes to have
+package access, rather than private access. Unfortunately this means the fields
+can be accessed directly by other classes in the same package, so you shouldn't
+use this in public API. As a rule of thumb, floating-point is about 2x slower than integer on
+Android-powered devices. In speed terms, there's no difference between Also, even for integers, some processors have hardware multiply but lack
+hardware divide. In such cases, integer division and modulus operations are
+performed in software—something to think about if you're designing a
+hash table or doing lots of math. In addition to all the usual reasons to prefer library code over rolling
+your own, bear in mind that the system is at liberty to replace calls
+to library methods with hand-coded assembler, which may be better than the
+best code the JIT can produce for the equivalent Java. The typical example
+here is {@link java.lang.String#indexOf String.indexOf()} and
+related APIs, which Dalvik replaces with
+an inlined intrinsic. Similarly, the {@link java.lang.System#arraycopy
+System.arraycopy()} method
+is about 9x faster than a hand-coded loop on a Nexus One with the JIT. Tip:
+Also see Josh Bloch's Effective Java, item 47. Developing your app with native code using the
+Android NDK
+isn't necessarily more efficient than programming with the
+Java language. For one thing,
+there's a cost associated with the Java-native transition, and the JIT can't
+optimize across these boundaries. If you're allocating native resources (memory
+on the native heap, file descriptors, or whatever), it can be significantly
+more difficult to arrange timely collection of these resources. You also
+need to compile your code for each architecture you wish to run on (rather
+than rely on it having a JIT). You may even have to compile multiple versions
+for what you consider the same architecture: native code compiled for the ARM
+processor in the G1 can't take full advantage of the ARM in the Nexus One, and
+code compiled for the ARM in the Nexus One won't run on the ARM in the G1. Native code is primarily useful when you have an existing native codebase
+that you want to port to Android, not for "speeding up" parts of your Android app
+written with the Java language. If you do need to use native code, you should read our
+JNI Tips. Tip:
+Also see Josh Bloch's Effective Java, item 54. On devices without a JIT, it is true that invoking methods via a
+variable with an exact type rather than an interface is slightly more
+efficient. (So, for example, it was cheaper to invoke methods on a
+ On devices without a JIT, caching field accesses is about 20% faster than
+repeatedly accesssing the field. With a JIT, field access costs about the same
+as local access, so this isn't a worthwhile optimization unless you feel it
+makes your code easier to read. (This is true of final, static, and static
+final fields too.)
+
+
+
+ Before you start optimizing, make sure you have a problem that you
+need to solve. Make sure you can accurately measure your existing performance,
+or you won't be able to measure the benefit of the alternatives you try. Every claim made in this document is backed up by a benchmark. The source
+to these benchmarks can be found in the code.google.com
+"dalvik" project. The benchmarks are built with the
+Caliper microbenchmarking
+framework for Java. Microbenchmarks are hard to get right, so Caliper goes out
+of its way to do the hard work for you, and even detect some cases where you're
+not measuring what you think you're measuring (because, say, the VM has
+managed to optimize all your code away). We highly recommend you use Caliper
+to run your own microbenchmarks. You may also find
+Traceview useful
+for profiling, but it's important to realize that it currently disables the JIT,
+which may cause it to misattribute time to code that the JIT may be able to win
+back. It's especially important after making changes suggested by Traceview
+data to ensure that the resulting code actually runs faster when run without
+Traceview. For more help profiling and debugging your apps, see the following documents: Android has security features built
+into the operating system that significantly reduce the frequency and impact of
+application security issues. The system is designed so you can typically build your apps with
+default system and file permissions and avoid difficult decisions about security. Some of the core security features that help you build secure apps
+include:
+ Nevertheless, it is important that you be familiar with the Android
+security best practices in this document. Following these practices as general coding habits
+will reduce the likelihood of inadvertently introducing security issues that
+adversely affect your users. The most common security concern for an application on Android is whether the data
+that you save on the device is accessible to other apps. There are three fundamental
+ways to save data on the device: By default, files that you create on internal
+storage are accessible only to your app. This
+protection is implemented by Android and is sufficient for most
+applications. You should generally avoid using the {@link android.content.Context#MODE_WORLD_WRITEABLE} or
+{@link android.content.Context#MODE_WORLD_READABLE} modes for
+IPC files because they do not provide
+the ability to limit data access to particular applications, nor do they
+provide any control on data format. If you want to share your data with other
+app processes, you might instead consider using a
+content provider, which
+offers read and write permissions to other apps and can make
+dynamic permission grants on a case-by-case basis. To provide additional protection for sensitive data, you might
+choose to encrypt local files using a key that is not directly accessible to the
+application. For example, a key can be placed in a {@link java.security.KeyStore}
+and protected with a user password that is not stored on the device. While this
+does not protect data from a root compromise that can monitor the user
+inputting the password, it can provide protection for a lost device without file system
+encryption. Files created on external
+storage, such as SD Cards, are globally readable and writable. Because
+external storage can be removed by the user and also modified by any
+application, you should not store sensitive information using
+external storage. As with data from any untrusted source, you should perform input
+validation when handling data from external storage.
+We strongly recommend that you not store executables or
+class files on external storage prior to dynamic loading. If your app
+does retrieve executable files from external storage, the files should be signed and
+cryptographically verified prior to dynamic loading. Content providers
+offer a structured storage mechanism that can be limited
+to your own application or exported to allow access by other applications.
+If you do not intend to provide other
+applications with access to your {@link android.content.ContentProvider}, mark them as When creating a {@link android.content.ContentProvider}
+that will be exported for use by other applications, you can specify a single
+permission
+ for reading and writing, or distinct permissions for reading and writing
+within the manifest. We recommend that you limit your permissions to those
+required to accomplish the task at hand. Keep in mind that it’s usually
+easier to add permissions later to expose new functionality than it is to take
+them away and break existing users. If you are using a content provider
+for sharing data between only your own apps, it is preferable to use the
+{@code
+android:protectionLevel} attribute set to {@code "signature"} protection.
+Signature permissions do not require user confirmation,
+so they provide a better user experience and more controlled access to the
+content provider data when the apps accessing the data are
+signed with
+the same key. Content providers can also provide more granular access by declaring the {@code
+android:grantUriPermissions} attribute and using the {@link
+android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} and {@link
+android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} flags in the
+{@link android.content.Intent} object
+that activates the component. The scope of these permissions can be further
+limited by the When accessing a content provider, use parameterized query methods such as
+{@link android.content.ContentProvider#query(Uri,String[],String,String[],String) query()},
+{@link android.content.ContentProvider#update(Uri,ContentValues,String,String[]) update()}, and
+{@link android.content.ContentProvider#delete(Uri,String,String[]) delete()} to avoid
+potential SQL injection from untrusted sources. Note that using parameterized methods is not
+sufficient if the Do not have a false sense of security about the write permission. Consider
+that the write permission allows SQL statements which make it possible for some
+data to be confirmed using creative Because Android sandboxes applications from each other, applications must explicitly
+share resources and data. They do this by declaring the permissions they need for additional
+capabilities not provided by the basic sandbox, including access to device features such as
+the camera. We recommend minimizing the number of permissions that your app requests
+Not having access to sensitive permissions reduces the risk of
+inadvertently misusing those permissions, can improve user adoption, and makes
+your app less for attackers. Generally,
+if a permission is not required for your app to function, do not request it. If it's possible to design your application in a way that does not require
+any permissions, that is preferable. For example, rather than requesting access
+to device information to create a unique identifier, create a GUID for your application
+(see the section about Handling User Data). Or, rather than
+using external storage (which requires permission), store data
+on the internal storage. In addition to requesting permissions, your application can use the {@code <permissions>}
+to protect IPC that is security sensitive and will be exposed to other
+applications, such as a {@link android.content.ContentProvider}.
+In general, we recommend using access controls
+other than user confirmed permissions where possible because permissions can
+be confusing for users. For example, consider using the signature
+protection level on permissions for IPC communication between applications
+provided by a single developer. Do not leak permission-protected data. This occurs when your app exposes data
+over IPC that is only available because it has a specific permission, but does
+not require that permission of any clients of it’s IPC interface. More
+details on the potential impacts, and frequency of this type of problem is
+provided in this research paper published at USENIX: http://www.cs.be
+rkeley.edu/~afelt/felt_usenixsec2011.pdf Generally, you should strive to define as few permissions as possible while
+satisfying your security requirements. Creating a new permission is relatively
+uncommon for most applications, because the system-defined
+permissions cover many situations. Where appropriate,
+perform access checks using existing permissions. If you must create a new permission, consider whether you can accomplish
+your task with a "signature"
+protection level. Signature permissions are transparent
+to the user and only allow access by applications signed by the same developer
+as application performing the permission check. If you create a permission with the "dangerous"
+protection level, there are a number of complexities
+that you need to consider:
+ Each of these poses a significant non-technical challenge for you as the developer
+while also confusing your users,
+which is why we discourage the use of the "dangerous" permission level. Network transactions are inherently risky for security, because it involves transmitting
+data that is potentially private to the user. People are increasingly aware of the privacy
+concerns of a mobile device, especially when the device performs network transactions,
+so it's very important that your app implement all best practices toward keeping the user's
+data secure at all times. Networking on Android is not significantly different from other Linux
+environments. The key consideration is making sure that appropriate protocols
+are used for sensitive data, such as {@link javax.net.ssl.HttpsURLConnection} for
+secure web traffic. We prefer use of HTTPS over HTTP anywhere that HTTPS is
+supported on the server, because mobile devices frequently connect on networks
+that are not secured, such as public Wi-Fi hotspots. Authenticated, encrypted socket-level communication can be easily
+implemented using the {@link javax.net.ssl.SSLSocket}
+class. Given the frequency with which Android devices connect to unsecured
+wireless networks using Wi-Fi, the use of secure networking is strongly
+encouraged for all applications that communicate over the network. We have seen some applications use localhost network ports for
+handling sensitive IPC. We discourage this approach since these interfaces are
+accessible by other applications on the device. Instead, you should use an Android IPC
+mechanism where authentication is possible such as with a {@link android.app.Service}. (Even
+worse than using loopback is to bind to INADDR_ANY since then your application
+may receive requests from anywhere.) Also, one common issue that warrants repeating is to make sure that you do
+not trust data downloaded from HTTP or other insecure protocols. This includes
+validation of input in {@link android.webkit.WebView} and
+any responses to intents issued against HTTP. The SMS protocol was primarily designed for
+user-to-user communication and is not well-suited for apps that want to transfer data.
+Due to the limitations of SMS, we strongly recommend the use of Google Cloud Messaging (GCM)
+and IP networking for sending data messages from a web server to your app on a user device. Beware that SMS is neither encrypted nor strongly
+authenticated on either the network or the device. In particular, any SMS receiver
+should expect that a malicious user may have sent the SMS to your application—Do
+not rely on unauthenticated SMS data to perform sensitive commands.
+Also, you should be aware that SMS may be subject to spoofing and/or
+interception on the network. On the Android-powered device itself, SMS
+messages are transmitted as broadcast intents, so they may be read or captured
+by other applications that have the {@link android.Manifest.permission#READ_SMS}
+permission. Insufficient input validation is one of the most common security problems
+affecting applications, regardless of what platform they run on. Android does
+have platform-level countermeasures that reduce the exposure of applications to
+input validation issues and you should use those features where possible. Also
+note that selection of type-safe languages tends to reduce the likelihood of
+input validation issues. If you are using native code, then any data read from files, received over
+the network, or received from an IPC has the potential to introduce a security
+issue. The most common problems are buffer overflows, use after
+free, and off-by-one errors.
+Android provides a number of technologies like ASLR and DEP that reduce the
+exploitability of these errors, but they do not solve the underlying problem.
+You can prevent these vulneratbilities by careful handling pointers and managing
+buffers. Dynamic, string based languages such as JavaScript and SQL are also subject
+to input validation problems due to escape characters and script injection. If you are using data within queries that are submitted to an SQL database or a
+content provider, SQL injection may be an issue. The best defense is to use
+parameterized queries, as is discussed in the above section about content providers.
+Limiting permissions to read-only or write-only can also reduce the potential
+for harm related to SQL injection. If you cannot use the security features above, we strongly recommend the use
+of well-structured data formats and verifying that the data conforms to the
+expected format. While blacklisting of characters or character-replacement can
+be an effective strategy, these techniques are error-prone in practice and
+should be avoided when possible. In general, the best approach for user data security is to minimize the use of APIs that access
+sensitive or personal user data. If you have access to user data and can avoid
+storing or transmitting the information, do not store or transmit the data.
+Finally, consider if there is a way that your application logic can be
+implemented using a hash or non-reversible form of the data. For example, your
+application might use the hash of an an email address as a primary key, to
+avoid transmitting or storing the email address. This reduces the chances of
+inadvertently exposing data, and it also reduces the chance of attackers
+attempting to exploit your application. If your application accesses personal information such as passwords or
+usernames, keep in mind that some jurisdictions may require you to provide a
+privacy policy explaining your use and storage of that data. So following the
+security best practice of minimizing access to user data may also simplify
+compliance. You should also consider whether your application might be inadvertently
+exposing personal information to other parties such as third-party components
+for advertising or third-party services used by your application. If you don't
+know why a component or service requires a personal information, don’t
+provide it. In general, reducing the access to personal information by your
+application will reduce the potential for problems in this area. If access to sensitive data is required, evaluate whether that information
+must be transmitted to a server, or whether the operation can be performed on
+the client. Consider running any code using sensitive data on the client to
+avoid transmitting user data. Also, make sure that you do not inadvertently expose user data to other
+application on the device through overly permissive IPC, world writable files,
+or network sockets. This is a special case of leaking permission-protected data,
+discussed in the Requesting Permissions section. If a GUID
+is required, create a large, unique number and store it. Do not
+use phone identifiers such as the phone number or IMEI which may be associated
+with personal information. This topic is discussed in more detail in the Android
+Developer Blog. Be careful when writing to on-device logs.
+In Android, logs are a shared resource, and are available
+to an application with the {@link android.Manifest.permission#READ_LOGS} permission.
+Even though the phone log data
+is temporary and erased on reboot, inappropriate logging of user information
+could inadvertently leak user data to other applications. Because {@link android.webkit.WebView} consumes web content that can include HTML and JavaScript,
+improper use can introduce common web security issues such as cross-site-scripting
+(JavaScript injection). Android includes a number of mechanisms to reduce
+the scope of these potential issues by limiting the capability of {@link android.webkit.WebView} to
+the minimum functionality required by your application. If your application does not directly use JavaScript within a {@link android.webkit.WebView}, do
+not call {@link android.webkit.WebSettings#setJavaScriptEnabled setJavaScriptEnabled()}.
+Some sample code uses this method, which you might repurpose in production
+application, so remove that method call if it's not required. By default,
+{@link android.webkit.WebView} does
+not execute JavaScript so cross-site-scripting is not possible. Use {@link android.webkit.WebView#addJavascriptInterface
+addJavaScriptInterface()} with
+particular care because it allows JavaScript to invoke operations that are
+normally reserved for Android applications. If you use it, expose
+{@link android.webkit.WebView#addJavascriptInterface addJavaScriptInterface()} only to
+web pages from which all input is trustworthy. If untrusted input is allowed,
+untrusted JavaScript may be able to invoke Android methods within your app. In general, we
+recommend exposing {@link android.webkit.WebView#addJavascriptInterface
+addJavaScriptInterface()} only to JavaScript that is contained within your application APK. If your application accesses sensitive data with a
+{@link android.webkit.WebView}, you may want to use the
+{@link android.webkit.WebView#clearCache clearCache()} method to delete any files stored
+locally. Server-side
+headers like In general, we recommend minimizing the frequency of asking for user
+credentials—to make phishing attacks more conspicuous, and less likely to be
+successful. Instead use an authorization token and refresh it. Where possible, username and password should not be stored on the device.
+Instead, perform initial authentication using the username and password
+supplied by the user, and then use a short-lived, service-specific
+authorization token. Services that will be accessible to multiple applications should be accessed
+using {@link android.accounts.AccountManager}. If possible, use the
+{@link android.accounts.AccountManager} class to invoke a cloud-based service and do not store
+passwords on the device. After using {@link android.accounts.AccountManager} to retrieve an
+{@link android.accounts.Account}, {@link android.accounts.Account#CREATOR}
+before passing in any credentials, so that you do not inadvertently pass
+credentials to the wrong application. If credentials are to be used only by applications that you create, then you
+can verify the application which accesses the {@link android.accounts.AccountManager} using
+{@link android.content.pm.PackageManager#checkSignatures checkSignature()}.
+Alternatively, if only one application will use the credential, you might use a
+{@link java.security.KeyStore} for storage. In addition to providing data isolation, supporting full-filesystem
+encryption, and providing secure communications channels, Android provides a
+wide array of algorithms for protecting data using cryptography. In general, try to use the highest level of pre-existing framework
+implementation that can support your use case. If you need to securely
+retrieve a file from a known location, a simple HTTPS URI may be adequate and
+requires no knowledge of cryptography. If you need a secure
+tunnel, consider using {@link javax.net.ssl.HttpsURLConnection} or
+{@link javax.net.ssl.SSLSocket}, rather than writing your own protocol. If you do find yourself needing to implement your own protocol, we strongly
+recommend that you not implement your own cryptographic algorithms. Use
+existing cryptographic algorithms such as those in the implementation of AES or
+RSA provided in the {@link javax.crypto.Cipher} class. Use a secure random number generator, {@link java.security.SecureRandom},
+to initialize any cryptographic keys, {@link javax.crypto.KeyGenerator}.
+Use of a key that is not generated with a secure random
+number generator significantly weakens the strength of the algorithm, and may
+allow offline attacks. If you need to store a key for repeated use, use a mechanism like
+ {@link java.security.KeyStore} that
+provides a mechanism for long term storage and retrieval of cryptographic
+keys. Some apps attempt to implement IPC using traditional Linux
+techniques such as network sockets and shared files. We strongly encourage you to instead
+use Android system functionality for IPC such as {@link android.content.Intent},
+{@link android.os.Binder} or {@link android.os.Messenger} with a {@link
+android.app.Service}, and {@link android.content.BroadcastReceiver}.
+The Android IPC mechanisms allow you to verify the identity of
+the application connecting to your IPC and set security policy for each IPC
+mechanism. Many of the security elements are shared across IPC mechanisms.
+If your IPC mechanism is not intended for use by other applications, set the
+{@code android:exported} attribute to {@code "false"} in the component's manifest element,
+such as for the {@code <service>}
+element. This is useful for applications that consist of multiple processes
+within the same UID, or if you decide late in development that you do not
+actually want to expose functionality as IPC but you don’t want to rewrite
+the code. If your IPC is intended to be accessible to other applications, you can
+apply a security policy by using the {@code <permission>}
+element. If IPC is between your own separate apps that are signed with the same key,
+it is preferable to use {@code "signature"} level permission in the {@code
+android:protectionLevel}. Intents are the preferred mechanism for asynchronous IPC in Android.
+Depending on your application requirements, you might use {@link
+android.content.Context#sendBroadcast sendBroadcast()}, {@link
+android.content.Context#sendOrderedBroadcast sendOrderedBroadcast()},
+or an explicit intent to a specific application component. Note that ordered broadcasts can be “consumed” by a recipient, so they
+may not be delivered to all applications. If you are sending an intent that muse be delivered
+to a specific receiver, then you must use an explicit intent that declares the receiver
+by nameintent. Senders of an intent can verify that the recipient has a permission
+specifying a non-Null permission with the method call. Only applications with that
+permission will receive the intent. If data within a broadcast intent may be
+sensitive, you should consider applying a permission to make sure that
+malicious applications cannot register to receive those messages without
+appropriate permissions. In those circumstances, you may also consider
+invoking the receiver directly, rather than raising a broadcast. Note: Intent filters should not be considered
+a security feature—components
+can be invoked with explicit intents and may not have data that would conform to the intent
+filter. You should perform input validation within your intent receiver to
+confirm that it is properly formatted for the invoked receiver, service, or
+activity. A {@link android.app.Service} is often used to supply functionality for other applications to
+use. Each service class must have a corresponding {@code By default, services are not exported and cannot be invoked by any other
+application. However, if you add any intent filters to the service declaration, then it is exported
+by default. It's best if you explicitly declare the {@code
+android:exported} attribute to be sure it behaves as you'd like.
+Services can also be protected using the {@code android:permission}
+attribute. By doing so, other applications will need to declare
+a corresponding A service can protect individual IPC calls into it with permissions, by
+calling {@link android.content.Context#checkCallingPermission
+checkCallingPermission()} before executing
+the implementation of that call. We generally recommend using the
+declarative permissions in the manifest, since those are less prone to
+oversight. Using {@link android.os.Binder} or {@link android.os.Messenger} is the
+preferred mechanism for RPC-style IPC in Android. They provide a well-defined
+interface that enables mutual authentication of the endpoints, if required. We strongly encourage designing interfaces in a manner that does not require
+interface specific permission checks. {@link android.os.Binder} and
+{@link android.os.Messenger} objects are not declared within the
+application manifest, and therefore you cannot apply declarative permissions
+directly to them. They generally inherit permissions declared in the
+application manifest for the {@link android.app.Service} or {@link
+android.app.Activity} within which they are
+implemented. If you are creating an interface that requires authentication
+and/or access controls, those controls must be
+explicitly added as code in the {@link android.os.Binder} or {@link android.os.Messenger}
+interface. If providing an interface that does require access controls, use {@link
+android.content.Context#checkCallingPermission checkCallingPermission()}
+to verify whether the
+caller has a required permission. This is especially important
+before accessing a service on behalf of the caller, as the identify of your
+application is passed to other interfaces. If invoking an interface provided
+by a {@link android.app.Service}, the {@link
+android.content.Context#bindService bindService()}
+ invocation may fail if you do not have permission to access the given service.
+ If calling an interface provided locally by your own application, it may be
+useful to use the {@link android.os.Binder#clearCallingIdentity clearCallingIdentity()}
+to satisfy internal security checks. For more information about performing IPC with a service, see
+Bound Services. A {@link android.content.BroadcastReceiver} handles asynchronous requests initiated by
+an {@link android.content.Intent}. By default, receivers are exported and can be invoked by any other
+application. If your {@link android.content.BroadcastReceiver}
+is intended for use by other applications, you
+may want to apply security permissions to receivers using the We strongly discourage loading code from outside of your application APK.
+Doing so significantly increases the likelihood of application compromise due
+to code injection or code tampering. It also adds complexity around version
+management and application testing. Finally, it can make it impossible to
+verify the behavior of an application, so it may be prohibited in some
+environments. If your application does dynamically load code, the most important thing to
+keep in mind about dynamically loaded code is that it runs with the same
+security permissions as the application APK. The user made a decision to
+install your application based on your identity, and they are expecting that
+you provide any code run within the application, including code that is
+dynamically loaded. The major security risk associated with dynamically loading code is that the
+code needs to come from a verifiable source. If the modules are included
+directly within your APK, then they cannot be modified by other applications.
+This is true whether the code is a native library or a class being loaded using
+{@link dalvik.system.DexClassLoader}. We have seen many instances of applications
+attempting to load code from insecure locations, such as downloaded from the
+network over unencrypted protocols or from world writable locations such as
+external storage. These locations could allow someone on the network to modify
+the content in transit, or another application on a users device to modify the
+content on the device, respectively. Dalvik is Android's runtime virtual machine (VM). Dalvik was built specifically for Android,
+but many of the concerns regarding secure code in other virtual machines also apply to Android.
+In general, you shouldn't concern yourself with security issues relating to the virtual machine.
+Your application runs in a secure sandbox environment, so other processes on the system cannnot
+access your code or private data. If you're interested in diving deeper on the subject of virtual machine security,
+we recommend that you familiarize yourself with some
+existing literature on the subject. Two of the more popular resources are:
+In this document
+
+
+
+What Triggers ANR?
+
+
+
+
+
+
+How to Avoid ANRs
+
+
+private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
+ // Do the long-running work in here
+ protected Long doInBackground(URL... urls) {
+ int count = urls.length;
+ long totalSize = 0;
+ for (int i = 0; i < count; i++) {
+ totalSize += Downloader.downloadFile(urls[i]);
+ publishProgress((int) ((i / (float) count) * 100));
+ // Escape early if cancel() is called
+ if (isCancelled()) break;
+ }
+ return totalSize;
+ }
+
+ // This is called each time you call publishProgress()
+ protected void onProgressUpdate(Integer... progress) {
+ setProgressPercent(progress[0]);
+ }
+
+ // This is called when doInBackground() is finished
+ protected void onPostExecute(Long result) {
+ showNotification("Downloaded " + result + " bytes");
+ }
+}
+
+
+
+new DownloadFilesTask().execute(url1, url2, url3);
+
+
+
+Reinforce Responsiveness
+
+
+
diff --git a/docs/html/training/articles/perf-jni.jd b/docs/html/training/articles/perf-jni.jd
new file mode 100644
index 000000000000..26b06b4f1a64
--- /dev/null
+++ b/docs/html/training/articles/perf-jni.jd
@@ -0,0 +1,719 @@
+page.title=JNI Tips
+@jd:body
+
+In this document
+
+
+
+UnsatisfiedLinkErrorFindClass find my class?JavaVM and JNIEnv
+
+GetEnv to discover the thread's JNIEnv. (Assuming it has one; see AttachCurrentThread below.)"jni.h" include file provides different typedefs
+depending on whether it's included into C or C++. For this reason it's a bad idea to
+include JNIEnv arguments in header files included by both languages. (Put another way: if your
+header file requires #ifdef __cplusplus, you may have to do some extra work if anything in
+that header refers to JNIEnv.)Threads
+
+Thread.start),
+but they can also be created elsewhere and then attached to the JavaVM. For
+example, a thread started with pthread_create can be attached
+with the JNI AttachCurrentThread or
+AttachCurrentThreadAsDaemon functions. Until a thread is
+attached, it has no JNIEnv, and cannot make JNI calls.java.lang.Thread
+object to be constructed and added to the "main" ThreadGroup,
+making it visible to the debugger. Calling AttachCurrentThread
+on an already-attached thread is a no-op.DetachCurrentThread before they exit.
+If coding this directly is awkward, in Android 2.0 (Eclair) and higher you
+can use pthread_key_create to define a destructor
+function that will be called before the thread exits, and
+call DetachCurrentThread from there. (Use that
+key with pthread_setspecific to store the JNIEnv in
+thread-local-storage; that way it'll be passed into your destructor as
+the argument.)jclass, jmethodID, and jfieldID
+
+
+
+
+FindClassGetFieldIDGetIntFieldjclass
+is a class reference and must be protected with a call
+to NewGlobalRef (see the next section). /*
+ * We use a class initializer to allow the native code to cache some
+ * field offsets. This native function looks up and caches interesting
+ * class/field/method IDs. Throws on failure.
+ */
+ private static native void nativeInit();
+
+ static {
+ nativeInit();
+ }
+
+nativeClassInit method in your C/C++ code that performs the ID lookups. The code
+will be executed once, when the class is initialized. If the class is ever unloaded and
+then reloaded, it will be executed again.Local and Global References
+
+jobject, including
+jclass, jstring, and jarray.
+(The runtime will warn you about most reference mis-uses when extended JNI
+checks are enabled.)NewGlobalRef and NewWeakGlobalRef.
+
+NewGlobalRef function takes the
+local reference as an argument and returns a global one.
+The global reference is guaranteed to be valid until you call
+DeleteGlobalRef.FindClass, e.g.:jclass localClass = env->FindClass("MyClass");
+jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
+
+NewGlobalRef on the same object may be different.
+To see if two references refer to the same object,
+you must use the IsSameObject function. Never compare
+references with == in native code.jobject values as keys.DeleteLocalRef instead of letting JNI do it for you. The
+implementation is only required to reserve slots for
+16 local references, so if you need more than that you should either delete as you go or use
+EnsureLocalCapacity/PushLocalFrame to reserve more.jfieldIDs and jmethodIDs are opaque
+types, not object references, and should not be passed to
+NewGlobalRef. The raw data
+pointers returned by functions like GetStringUTFChars
+and GetByteArrayElements are also not objects. (They may be passed
+between threads, and are valid until the matching Release call.)AttachCurrentThread, the code you are running will
+never automatically free local references until the thread detaches. Any local
+references you create will have to be deleted manually. In general, any native
+code that creates local references in a loop probably needs to do some manual
+deletion.UTF-8 and UTF-16 Strings
+
+GetStringChars, whereas
+GetStringUTFChars requires an allocation and a conversion to
+UTF-8. Note that
+UTF-16 strings are not zero-terminated, and \u0000 is allowed,
+so you need to hang on to the string length as well as
+the jchar pointer.Release the strings you Get. The
+string functions return jchar* or jbyte*, which
+are C-style pointers to primitive data rather than local references. They
+are guaranteed valid until Release is called, which means they are not
+released when the native method returns.NewStringUTF without filtering it.
+Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
+characters or convert them to proper Modified UTF-8 form. If you don't,
+the UTF-16 conversion will likely not be what you expect. The extended
+JNI checks will scan strings and warn you about invalid data, but they
+won't catch everything.Primitive Arrays
+
+Get<PrimitiveType>ArrayElements
+family of calls allows the runtime to either return a pointer to the actual elements, or
+allocate some memory and make a copy. Either way, the raw pointer returned
+is guaranteed to be valid until the corresponding Release call
+is issued (which implies that, if the data wasn't copied, the array object
+will be pinned down and can't be relocated as part of compacting the heap).
+You must Release every array you Get. Also, if the Get
+call fails, you must ensure that your code doesn't try to Release a NULL
+pointer later.isCopy argument. This is rarely
+useful.Release call takes a mode argument that can
+have one of three values. The actions performed by the runtime depend upon
+whether it returned a pointer to the actual data or a copy of it:
+
+
+0
+
+
+ JNI_COMMIT
+
+
+ JNI_ABORT
+
+
+isCopy flag is to know if
+you need to call Release with JNI_COMMIT
+after making changes to an array — if you're alternating between making
+changes and executing code that uses the contents of the array, you may be
+able to
+skip the no-op commit. Another possible reason for checking the flag is for
+efficient handling of JNI_ABORT. For example, you might want
+to get an array, modify it in place, pass pieces to other functions, and
+then discard the changes. If you know that JNI is making a new copy for
+you, there's no need to create another "editable" copy. If JNI is passing
+you the original, then you do need to make your own copy.Release call if
+*isCopy is false. This is not the case. If no copy buffer was
+allocated, then the original memory must be pinned down and can't be moved by
+the garbage collector.JNI_COMMIT flag does not release the array,
+and you will need to call Release again with a different flag
+eventually.Region Calls
+
+Get<Type>ArrayElements
+and GetStringChars that may be very helpful when all you want
+to do is copy data in or out. Consider the following: jbyte* data = env->GetByteArrayElements(array, NULL);
+ if (data != NULL) {
+ memcpy(buffer, data, len);
+ env->ReleaseByteArrayElements(array, data, JNI_ABORT);
+ }
+
+len byte
+elements out of it, and then releases the array. Depending upon the
+implementation, the Get call will either pin or copy the array
+contents.
+The code copies the data (for perhaps a second time), then calls Release; in this case
+JNI_ABORT ensures there's no chance of a third copy. env->GetByteArrayRegion(array, 0, len, buffer);
+
+
+
+
+Release after something fails.
+Set<Type>ArrayRegion call
+to copy data into an array, and GetStringRegion or
+GetStringUTFRegion to copy characters out of a
+String.
+
+
+
+Exceptions
+
+ExceptionCheck, or ExceptionOccurred) and return,
+or clear the exception and handle it.
+
+
+DeleteGlobalRef
+ DeleteLocalRef
+ DeleteWeakGlobalRef
+ ExceptionCheck
+ ExceptionClear
+ ExceptionDescribe
+ ExceptionOccurred
+ MonitorExit
+ PopLocalFrame
+ PushLocalFrame
+ Release<PrimitiveType>ArrayElements
+ ReleasePrimitiveArrayCritical
+ ReleaseStringChars
+ ReleaseStringCritical
+ ReleaseStringUTFChars
+NewString returns
+a non-NULL value, you don't need to check for an exception. However, if
+you call a method (using a function like CallObjectMethod),
+you must always check for an exception, because the return value is not
+going to be valid if an exception was thrown.Throw and ThrowNew instructions just
+set an exception pointer in the current thread. Upon returning to managed
+from native code, the exception will be noted and handled appropriately.ExceptionCheck or
+ExceptionOccurred, and clear it with
+ExceptionClear. As usual,
+discarding exceptions without handling them can lead to problems.Throwable object
+itself, so if you want to (say) get the exception string you will need to
+find the Throwable class, look up the method ID for
+getMessage "()Ljava/lang/String;", invoke it, and if the result
+is non-NULL use GetStringUTFChars to get something you can
+hand to printf(3) or equivalent.Extended Checking
+
+
+
+
+NewDirectByteBuffer.Call*Method JNI call: incorrect return type, static/non-static mismatch, wrong type for ‘this’ (for non-static calls) or wrong class (for static calls).DeleteGlobalRef/DeleteLocalRef on the wrong kind of reference.0, JNI_ABORT, or JNI_COMMIT).adb shell stop
+adb shell setprop dalvik.vm.checkjni true
+adb shell start
+
+D AndroidRuntime: CheckJNI is ON
+
+adb shell setprop debug.checkjni 1
+
+D Late-enabling CheckJNI
+
+
+
+
+
+Native Libraries
+
+System.loadLibrary call. The
+preferred way to get at your native code is:
+
+
+System.loadLibrary from a static class
+initializer. (See the earlier example, where one is used to call
+nativeClassInit.) The argument is the "undecorated"
+library name, so to load "libfubar.so" you would pass in "fubar".jint JNI_OnLoad(JavaVM* vm, void* reserved)JNI_OnLoad, register all of your native methods. You
+should declare
+the methods "static" so the names don't take up space in the symbol table
+on the device.JNI_OnLoad function should look something like this if
+written in C++:jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ JNIEnv* env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ return -1;
+ }
+
+ // Get jclass with env->FindClass.
+ // Register methods with env->RegisterNatives.
+
+ return JNI_VERSION_1_6;
+}
+
+System.load with the full path name of the
+shared library. For Android apps, you may find it useful to get the full
+path to the application's private data storage area from the context object.JNI_OnLoad function.
+You can instead use "discovery" of native methods that are named in a
+specific way (see the JNI spec for details), though this is less desirable because if a method signature is wrong you won't know
+about it until the first time the method is actually used.JNI_OnLoad: any FindClass
+calls you make from there will happen in the context of the class loader
+that was used to load the shared library. Normally FindClass
+uses the loader associated with the method at the top of the interpreted
+stack, or if there isn't one (because the thread was just attached) it uses
+the "system" class loader. This makes
+JNI_OnLoad a convenient place to look up and cache class
+object references.64-bit Considerations
+
+long field rather than an int.
+
+
+
+Unsupported Features/Backwards Compatibility
+
+
+
+
+DefineClass is not implemented. Android does not use
+ Java bytecodes or class files, so passing in binary class data
+ doesn't work.
+
+
+
+
+pthread_key_create
+ destructor function to avoid the "thread must be detached before
+ exit" check. (The runtime also uses a pthread key destructor function,
+ so it'd be a race to see which gets called first.)
+ NewLocalRef, NewGlobalRef, and
+ DeleteWeakGlobalRef. (The spec strongly encourages
+ programmers to create hard references to weak globals before doing
+ anything with them, so this should not be at all limiting.)
+ GetObjectRefType
+ GetObjectRefType correctly. Instead we used a heuristic
+ that looked through the weak globals table, the arguments, the locals
+ table, and the globals table in that order. The first time it found your
+ direct pointer, it would report that your reference was of the type it
+ happened to be examining. This meant, for example, that if
+ you called GetObjectRefType on a global jclass that happened
+ to be the same as the jclass passed as an implicit argument to your static
+ native method, you'd get JNILocalRefType rather than
+ JNIGlobalRefType.
+FAQ: Why do I get
+
+UnsatisfiedLinkError?java.lang.UnsatisfiedLinkError: Library foo not found
+
+dlopen(3), and
+the details of the failure can be found in the exception's detail message.
+
+
+adb shell ls -l <path> to check its presence
+ and permissions.
+ UnsatisfiedLinkError failures looks like:java.lang.UnsatisfiedLinkError: myfunc
+ at Foo.myfunc(Native Method)
+ at Foo.main(Foo.java:10)
+
+W/dalvikvm( 880): No implementation found for native LFoo;.myfunc ()V
+
+
+
+
+
+
+extern "C" and appropriate
+ visibility (JNIEXPORT). Note that prior to Ice Cream
+ Sandwich, the JNIEXPORT macro was incorrect, so using a new GCC with
+ an old jni.h won't work.
+ You can use arm-eabi-nm
+ to see the symbols as they appear in the library; if they look
+ mangled (something like _Z15Java_Foo_myfuncP7_JNIEnvP7_jclass
+ rather than Java_Foo_myfunc), or if the symbol type is
+ a lowercase 't' rather than an uppercase 'T', then you need to
+ adjust the declaration.
+ byte and 'Z' is boolean.
+ Class name components in signatures start with 'L', end with ';',
+ use '/' to separate package/class names, and use '$' to separate
+ inner-class names (Ljava/util/Map$Entry;, say).
+ javah to automatically generate JNI headers may help
+avoid some problems.
+
+
+
+FAQ: Why didn't
+
+FindClass find my class?java/lang/String. If you're looking up an array class,
+you need to start with the appropriate number of square brackets and
+must also wrap the class with 'L' and ';', so a one-dimensional array of
+String would be [Ljava/lang/String;.FindClass wants to start the class search in the
+class loader associated with your code. It examines the call stack,
+which will look something like:
+ Foo.myfunc(Native Method)
+ Foo.main(Foo.java:10)
+ dalvik.system.NativeStart.main(Native Method)
+
+Foo.myfunc. FindClass
+finds the ClassLoader object associated with the Foo
+class and uses that.pthread_create
+and then attaching it with AttachCurrentThread).
+Now the stack trace looks like this: dalvik.system.NativeStart.run(Native Method)
+
+NativeStart.run, which isn't part of
+your application. If you call FindClass from this thread, the
+JavaVM will start in the "system" class loader instead of the one associated
+with your application, so attempts to find app-specific classes will fail.
+
+
+
+
+FindClass lookups once, in
+ JNI_OnLoad, and cache the class references for later
+ use. Any FindClass calls made as part of executing
+ JNI_OnLoad will use the class loader associated with
+ the function that called System.loadLibrary (this is a
+ special rule, provided to make library initialization more convenient).
+ If your app code is loading the library, FindClass
+ will use the correct class loader.
+ Foo.class in.
+ ClassLoader object somewhere
+ handy, and issue loadClass calls directly. This requires
+ some effort.
+FAQ: How do I share raw data with native code?
+
+byte[]. This allows very fast
+access from managed code. On the native side, however, you're
+not guaranteed to be able to access the data without having to copy it. In
+some implementations, GetByteArrayElements and
+GetPrimitiveArrayCritical will return actual pointers to the
+raw data in the managed heap, but in others it will allocate a buffer
+on the native heap and copy the data over.java.nio.ByteBuffer.allocateDirect, or
+the JNI NewDirectByteBuffer function. Unlike regular
+byte buffers, the storage is not allocated on the managed heap, and can
+always be accessed directly from native code (get the address
+with GetDirectBufferAddress). Depending on how direct
+byte buffer access is implemented, accessing the data from managed code
+can be very slow.
+
+
+ByteBuffer might be unwise.)
+In this document
+
+
+
+
+
+
+Avoid Creating Unnecessary Objects
+
+
+
+
+
+
+
+Prefer Static Over Virtual
+
+Use Static Final For Constants
+
+
+static int intVal = 42;
+static String strVal = "Hello, world!";
+
+
+<clinit>, that is executed when the class is first used.
+The method stores the value 42 into intVal, and extracts a
+reference from the classfile string constant table for strVal.
+When these values are referenced later on, they are accessed with field
+lookups.
+static final int intVal = 42;
+static final String strVal = "Hello, world!";
+
+
+<clinit> method,
+because the constants go into static field initializers in the dex file.
+Code that refers to intVal will use
+the integer value 42 directly, and accesses to strVal will
+use a relatively inexpensive "string constant" instruction instead of a
+field lookup.static final whenever possible.Avoid Internal Getters/Setters
+
+i = getCount()) instead of accessing the field directly (i
+= mCount). This is an excellent habit for C++ and is often practiced in other
+object oriented languages like C# and Java, because the compiler can
+usually inline the access, and if you need to restrict or debug field access
+you can add the code at any time.Use Enhanced For Loop Syntax
+
+for loop (also sometimes known as "for-each" loop) can be used
+for collections that implement the {@link java.lang.Iterable} interface and for arrays.
+With collections, an iterator is allocated to make interface calls
+to {@code hasNext()} and {@code next()}. With an {@link java.util.ArrayList},
+a hand-written counted loop is
+about 3x faster (with or without JIT), but for other collections the enhanced
+for loop syntax will be exactly equivalent to explicit iterator usage.
+static class Foo {
+ int mSplat;
+}
+
+Foo[] mArray = ...
+
+public void zero() {
+ int sum = 0;
+ for (int i = 0; i < mArray.length; ++i) {
+ sum += mArray[i].mSplat;
+ }
+}
+
+public void one() {
+ int sum = 0;
+ Foo[] localArray = mArray;
+ int len = localArray.length;
+
+ for (int i = 0; i < len; ++i) {
+ sum += localArray[i].mSplat;
+ }
+}
+
+public void two() {
+ int sum = 0;
+ for (Foo a : mArray) {
+ sum += a.mSplat;
+ }
+}
+
+
+zero() is slowest, because the JIT can't yet optimize away
+the cost of getting the array length once for every iteration through the
+loop.one() is faster. It pulls everything out into local
+variables, avoiding the lookups. Only the array length offers a performance
+benefit.two() is fastest for devices without a JIT, and
+indistinguishable from one() for devices with a JIT.
+It uses the enhanced for loop syntax introduced in version 1.5 of the Java
+programming language.for loop by default, but consider a
+hand-written counted loop for performance-critical {@link java.util.ArrayList} iteration.Consider Package Instead of Private Access with Private Inner Classes
+
+
+public class Foo {
+ private class Inner {
+ void stuff() {
+ Foo.this.doStuff(Foo.this.mValue);
+ }
+ }
+
+ private int mValue;
+
+ public void run() {
+ Inner in = new Inner();
+ mValue = 27;
+ in.stuff();
+ }
+
+ private void doStuff(int value) {
+ System.out.println("Value is " + value);
+ }
+}
+
+Foo$Inner) that directly accesses a private method and a private
+instance field in the outer class. This is legal, and the code prints "Value is
+27" as expected.Foo's
+private members from Foo$Inner to be illegal because
+Foo and Foo$Inner are different classes, even though
+the Java language allows an inner class to access an outer class' private
+members. To bridge the gap, the compiler generates a couple of synthetic
+methods:
+/*package*/ static int Foo.access$100(Foo foo) {
+ return foo.mValue;
+}
+/*package*/ static void Foo.access$200(Foo foo, int value) {
+ foo.doStuff(value);
+}
+
+mValue field or invoke the doStuff() method
+in the outer class. What this means is that the code above really boils down to
+a case where you're accessing member fields through accessor methods.
+Earlier we talked about how accessors are slower than direct field
+accesses, so this is an example of a certain language idiom resulting in an
+"invisible" performance hit.Avoid Using Floating-Point
+
+float and
+double on the more modern hardware. Space-wise, double
+is 2x larger. As with desktop machines, assuming space isn't an issue, you
+should prefer double to float.Know and Use the Libraries
+
+Use Native Methods Carefully
+
+Performance Myths
+
+
+HashMap map than a Map map, even though in both
+cases the map was a HashMap.) It was not the case that this
+was 2x slower; the actual difference was more like 6% slower. Furthermore,
+the JIT makes the two effectively indistinguishable.Always Measure
+
+In this document
+
+
+See also
+
+
+
+
+Storing Data
+
+Using internal storage
+
+Using external storage
+
+Using content providers
+
+
+android:exported=false in the application manifest. Otherwise, set the android:exported
+attribute {@code "true"} to allow other apps to access the stored data.
+
+<grant-uri-permission element>.selection argument is built by concatenating user data
+prior to submitting it to the method.WHERE clauses and parsing the
+results. For example, an attacker might probe for presence of a specific phone
+number in a call-log by modifying a row only if that phone number already
+exists. If the content provider data has predictable structure, the write
+permission may be equivalent to providing both reading and writing.Using Permissions
+
+Requesting Permissions
+
+Creating Permissions
+
+
+
+
+Using Networking
+
+Using IP Networking
+
+Using Telephony Networking
+
+Performing Input Validation
+
+Handling User Data
+
+Using WebView
+
+no-cache can also be used to indicate that an application should
+not cache particular content.Handling Credentials
+
+Using Cryptography
+
+Using Interprocess Communication
+
+Using intents
+
+Using services
+
+<uses-permission>
+ element in their own manifest to be
+able to start, stop, or bind to the service.Using binder and messenger interfaces
+
+Using broadcast receivers
+
+
+<receiver> element within the application manifest. This will
+prevent applications without appropriate permissions from sending an intent to
+the {@link android.content.BroadcastReceiver}.Dynamically Loading Code
+
+Security in a Virtual Machine
+
+
This document is focused on the areas which are Android specific or +different from other VM environments. For developers experienced with VM +programming in other environments, there are two broad issues that may be +different about writing apps for Android: +
In general, we encourage developers to use the Android SDK for +application development, rather than using native code with the +Android NDK. Applications built +with native code are more complex, less portable, and more like to include +common memory corruption errors such as buffer overflows.
+ +Android is built using the Linux kernel and being familiar with Linux +development security best practices is especially useful if you are going to +use native code. Linux security practices are beyond the scope of this document, +but one of the most popular resources is “Secure Programming for +Linux and Unix HOWTO”, available at +http://www.dwheeler.com/secure-programs.
+ +An important difference between Android and most Linux environments is the +Application Sandbox. On Android, all applications run in the Application +Sandbox, including those written with native code. At the most basic level, a +good way to think about it for developers familiar with Linux is to know that +every application is given a unique UID +with very limited permissions. This is discussed in more detail in the Android Security +Overview and you should be familiar with application permissions even if +you are using native code.
+ diff --git a/docs/html/training/perf-anr.jd b/docs/html/training/perf-anr.jd deleted file mode 100644 index 864fb3403536..000000000000 --- a/docs/html/training/perf-anr.jd +++ /dev/null @@ -1,196 +0,0 @@ -page.title=Keeping Your App Responsive -@jd:body - -
-Figure 1. An ANR dialog displayed to the user.
-It's possible to write code that wins every performance test in the world, -but still feels sluggish, hang or freeze for significant periods, or take too -long to process input. The worst thing that can happen to your app's responsiveness -is an "Application Not Responding" (ANR) dialog.
- -In Android, the system guards against applications that are insufficiently -responsive for a period of time by displaying a dialog that says your app has -stopped responding, such as the dialog -in Figure 1. At this point, your app has been unresponsive for a considerable -period of time so the system offers the user an option to quit the app. It's critical -to design responsiveness into your application so the system never displays -an ANR dialog to the user.
- -This document describes how the Android system determines whether an -application is not responding and provides guidelines for ensuring that your -application stays responsive.
- - -Generally, the system displays an ANR if an application cannot respond to -user input. For example, if an application blocks on some I/O operation -(frequently a network access) on the UI thread so the system can't -process incoming user input events. Or perhaps the app -spends too much time building an elaborate in-memory -structure or computing the next move in a game on the UI thread. It's always important to make -sure these computations are efficient, but even the -most efficient code still takes time to run.
- -In any situation in which your app performs a potentially lengthy operation, -you should not perform the work on the UI thread, but instead create a -worker thread and do most of the work there. This keeps the UI thread (which drives the user -interface event loop) running and prevents the system from concluding that your code -has frozen. Because such threading usually is accomplished at the class -level, you can think of responsiveness as a class problem. (Compare -this with basic code performance, which is a method-level -concern.)
- -In Android, application responsiveness is monitored by the Activity Manager -and Window Manager system services. Android will display the ANR dialog -for a particular application when it detects one of the following -conditions:
-Android applications normally run entirely on a single thread by default -the "UI thread" or "main thread"). -This means anything your application is doing in the UI thread that -takes a long time to complete can trigger the ANR dialog because your -application is not giving itself a chance to handle the input event or intent -broadcasts.
- -Therefore, any method that runs in the UI thread should do as little work -as possible on that thread. In particular, activities should do as little as possible to set -up in key life-cycle methods such as {@link android.app.Activity#onCreate onCreate()} -and {@link android.app.Activity#onResume onResume()}. -Potentially long running operations such as network -or database operations, or computationally expensive calculations such as -resizing bitmaps should be done in a worker thread (or in the case of databases -operations, via an asynchronous request).
- -The most effecive way to create a worker thread for longer -operations is with the {@link android.os.AsyncTask} -class. Simply extend {@link android.os.AsyncTask} and implement the -{@link android.os.AsyncTask#doInBackground doInBackground()} method to perform the work. -To post progress changes to the user, you can call - {@link android.os.AsyncTask#publishProgress publishProgress()}, which invokes the - {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} callback method. From your - implementation of {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} (which - runs on the UI thread), you can notify the user. For example:
- -
-private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
- // Do the long-running work in here
- protected Long doInBackground(URL... urls) {
- int count = urls.length;
- long totalSize = 0;
- for (int i = 0; i < count; i++) {
- totalSize += Downloader.downloadFile(urls[i]);
- publishProgress((int) ((i / (float) count) * 100));
- // Escape early if cancel() is called
- if (isCancelled()) break;
- }
- return totalSize;
- }
-
- // This is called each time you call publishProgress()
- protected void onProgressUpdate(Integer... progress) {
- setProgressPercent(progress[0]);
- }
-
- // This is called when doInBackground() is finished
- protected void onPostExecute(Long result) {
- showNotification("Downloaded " + result + " bytes");
- }
-}
-
-
- To execute this worker thread, simply create an instance and - call {@link android.os.AsyncTask#execute execute()}:
- --new DownloadFilesTask().execute(url1, url2, url3); -- - -
Although it's more complicated than {@link android.os.AsyncTask}, you might want to instead -create your own {@link java.lang.Thread} or {@link android.os.HandlerThread} class. If you do, -you should set the thread priority to "background" priority by calling {@link -android.os.Process#setThreadPriority Process.setThreadPriority()} and passing {@link -android.os.Process#THREAD_PRIORITY_BACKGROUND}. If you don't set the thread to a lower priority -this way, then the thread could still slow down your app because it operates at the same priority -as the UI thread by default.
- -If you implement {@link java.lang.Thread} or {@link android.os.HandlerThread}, -be sure that your UI thread does not block while waiting for the worker thread to -complete—do not call {@link java.lang.Thread#wait Thread.wait()} or -{@link java.lang.Thread#sleep Thread.sleep()}. Instead of blocking while waiting for a worker -thread to complete, your main thread should provide a {@link -android.os.Handler} for the other threads to post back to upon completion. -Designing your application in this way will allow your app's UI thread to remain -responsive to input and thus avoid ANR dialogs caused by the 5 second input -event timeout.
- -The specific constraint on {@link android.content.BroadcastReceiver} execution time -emphasizes what broadcast receivers are meant to do: -small, discrete amounts of work in the background such -as saving a setting or registering a {@link android.app.Notification}. So as with other methods -called in the UI thread, applications should avoid potentially long-running -operations or calculations in a broadcast receiver. But instead of doing intensive -tasks via worker threads, your -application should start an {@link android.app.IntentService} if a -potentially long running action needs to be taken in response to an intent -broadcast.
- -Tip: -You can use {@link android.os.StrictMode} to help find potentially -long running operations such as network or database operations that -you might accidentally be doing your main thread.
- - - -Generally, 100 to 200ms is the threshold beyond which users will perceive -slowness in an application. As such, here -are some additional tips beyond what you should do to avoid ANR and -make your application seem responsive to users:
- -UnsatisfiedLinkErrorFindClass find my class?JNI is the Java Native Interface. It defines a way for managed code -(written in the Java programming language) to interact with native -code (written in C/C++). It's vendor-neutral, has support for loading code from -dynamic shared libraries, and while cumbersome at times is reasonably efficient.
- -You really should read through the -JNI spec for J2SE 6 -to get a sense for how JNI works and what features are available. Some -aspects of the interface aren't immediately obvious on -first reading, so you may find the next few sections handy. -There's a more detailed JNI Programmer's Guide and Specification.
- - - -JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially -pointers to pointers to function tables. (In the C++ version, they're classes with a -pointer to a function table and a member function for each JNI function that indirects through -the table.) The JavaVM provides the "invocation interface" functions, -which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process, -but Android only allows one.
- -The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as -the first argument.
- -The JNIEnv is used for thread-local storage. For this reason, you cannot share a JNIEnv between threads.
-If a piece of code has no other way to get its JNIEnv, you should share
-the JavaVM, and use GetEnv to discover the thread's JNIEnv. (Assuming it has one; see AttachCurrentThread below.)
The C declarations of JNIEnv and JavaVM are different from the C++
-declarations. The "jni.h" include file provides different typedefs
-depending on whether it's included into C or C++. For this reason it's a bad idea to
-include JNIEnv arguments in header files included by both languages. (Put another way: if your
-header file requires #ifdef __cplusplus, you may have to do some extra work if anything in
-that header refers to JNIEnv.)
All threads are Linux threads, scheduled by the kernel. They're usually
-started from managed code (using Thread.start),
-but they can also be created elsewhere and then attached to the JavaVM. For
-example, a thread started with pthread_create can be attached
-with the JNI AttachCurrentThread or
-AttachCurrentThreadAsDaemon functions. Until a thread is
-attached, it has no JNIEnv, and cannot make JNI calls.
Attaching a natively-created thread causes a java.lang.Thread
-object to be constructed and added to the "main" ThreadGroup,
-making it visible to the debugger. Calling AttachCurrentThread
-on an already-attached thread is a no-op.
Android does not suspend threads executing native code. If -garbage collection is in progress, or the debugger has issued a suspend -request, Android will pause the thread the next time it makes a JNI call.
- -Threads attached through JNI must call
-DetachCurrentThread before they exit.
-If coding this directly is awkward, in Android 2.0 (Eclair) and higher you
-can use pthread_key_create to define a destructor
-function that will be called before the thread exits, and
-call DetachCurrentThread from there. (Use that
-key with pthread_setspecific to store the JNIEnv in
-thread-local-storage; that way it'll be passed into your destructor as
-the argument.)
If you want to access an object's field from native code, you would do the following:
- -FindClassGetFieldIDGetIntFieldSimilarly, to call a method, you'd first get a class object reference and then a method ID. The IDs are often just -pointers to internal runtime data structures. Looking them up may require several string -comparisons, but once you have them the actual call to get the field or invoke the method -is very quick.
- -If performance is important, it's useful to look the values up once and cache the results -in your native code. Because there is a limit of one JavaVM per process, it's reasonable -to store this data in a static local structure.
- -The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes
-are only unloaded if all classes associated with a ClassLoader can be garbage collected,
-which is rare but will not be impossible in Android. Note however that
-the jclass
-is a class reference and must be protected with a call
-to NewGlobalRef (see the next section).
If you would like to cache the IDs when a class is loaded, and automatically re-cache them -if the class is ever unloaded and reloaded, the correct way to initialize -the IDs is to add a piece of code that looks like this to the appropriate class:
- - /*
- * We use a class initializer to allow the native code to cache some
- * field offsets. This native function looks up and caches interesting
- * class/field/method IDs. Throws on failure.
- */
- private static native void nativeInit();
-
- static {
- nativeInit();
- }
-
-Create a nativeClassInit method in your C/C++ code that performs the ID lookups. The code
-will be executed once, when the class is initialized. If the class is ever unloaded and
-then reloaded, it will be executed again.
Every argument passed to a native method, and almost every object returned -by a JNI function is a "local reference". This means that it's valid for the -duration of the current native method in the current thread. -Even if the object itself continues to live on after the native method -returns, the reference is not valid. -
This applies to all sub-classes of jobject, including
-jclass, jstring, and jarray.
-(The runtime will warn you about most reference mis-uses when extended JNI
-checks are enabled.)
The only way to get non-local references is via the functions
-NewGlobalRef and NewWeakGlobalRef.
-
-
If you want to hold on to a reference for a longer period, you must use
-a "global" reference. The NewGlobalRef function takes the
-local reference as an argument and returns a global one.
-The global reference is guaranteed to be valid until you call
-DeleteGlobalRef.
This pattern is commonly used when caching a jclass returned
-from FindClass, e.g.:
jclass localClass = env->FindClass("MyClass");
-jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
-
-All JNI methods accept both local and global references as arguments.
-It's possible for references to the same object to have different values.
-For example, the return values from consecutive calls to
-NewGlobalRef on the same object may be different.
-To see if two references refer to the same object,
-you must use the IsSameObject function. Never compare
-references with == in native code.
One consequence of this is that you
-must not assume object references are constant or unique
-in native code. The 32-bit value representing an object may be different
-from one invocation of a method to the next, and it's possible that two
-different objects could have the same 32-bit value on consecutive calls. Do
-not use jobject values as keys.
Programmers are required to "not excessively allocate" local references. In practical terms this means
-that if you're creating large numbers of local references, perhaps while running through an array of
-objects, you should free them manually with
-DeleteLocalRef instead of letting JNI do it for you. The
-implementation is only required to reserve slots for
-16 local references, so if you need more than that you should either delete as you go or use
-EnsureLocalCapacity/PushLocalFrame to reserve more.
Note that jfieldIDs and jmethodIDs are opaque
-types, not object references, and should not be passed to
-NewGlobalRef. The raw data
-pointers returned by functions like GetStringUTFChars
-and GetByteArrayElements are also not objects. (They may be passed
-between threads, and are valid until the matching Release call.)
One unusual case deserves separate mention. If you attach a native
-thread with AttachCurrentThread, the code you are running will
-never automatically free local references until the thread detaches. Any local
-references you create will have to be deleted manually. In general, any native
-code that creates local references in a loop probably needs to do some manual
-deletion.
The Java programming language uses UTF-16. For convenience, JNI provides methods that work with Modified UTF-8 as well. The -modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00. -The nice thing about this is that you can count on having C-style zero-terminated strings, -suitable for use with standard libc string functions. The down side is that you cannot pass -arbitrary UTF-8 data to JNI and expect it to work correctly.
- -If possible, it's usually faster to operate with UTF-16 strings. Android
-currently does not require a copy in GetStringChars, whereas
-GetStringUTFChars requires an allocation and a conversion to
-UTF-8. Note that
-UTF-16 strings are not zero-terminated, and \u0000 is allowed,
-so you need to hang on to the string length as well as
-the jchar pointer.
Don't forget to Release the strings you Get. The
-string functions return jchar* or jbyte*, which
-are C-style pointers to primitive data rather than local references. They
-are guaranteed valid until Release is called, which means they are not
-released when the native method returns.
Data passed to NewStringUTF must be in Modified UTF-8 format. A
-common mistake is reading character data from a file or network stream
-and handing it to NewStringUTF without filtering it.
-Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
-characters or convert them to proper Modified UTF-8 form. If you don't,
-the UTF-16 conversion will likely not be what you expect. The extended
-JNI checks will scan strings and warn you about invalid data, but they
-won't catch everything.
JNI provides functions for accessing the contents of array objects. -While arrays of objects must be accessed one entry at a time, arrays of -primitives can be read and written directly as if they were declared in C.
- -To make the interface as efficient as possible without constraining
-the VM implementation, the Get<PrimitiveType>ArrayElements
-family of calls allows the runtime to either return a pointer to the actual elements, or
-allocate some memory and make a copy. Either way, the raw pointer returned
-is guaranteed to be valid until the corresponding Release call
-is issued (which implies that, if the data wasn't copied, the array object
-will be pinned down and can't be relocated as part of compacting the heap).
-You must Release every array you Get. Also, if the Get
-call fails, you must ensure that your code doesn't try to Release a NULL
-pointer later.
You can determine whether or not the data was copied by passing in a
-non-NULL pointer for the isCopy argument. This is rarely
-useful.
The Release call takes a mode argument that can
-have one of three values. The actions performed by the runtime depend upon
-whether it returned a pointer to the actual data or a copy of it:
0
- JNI_COMMIT
- JNI_ABORT
- One reason for checking the isCopy flag is to know if
-you need to call Release with JNI_COMMIT
-after making changes to an array — if you're alternating between making
-changes and executing code that uses the contents of the array, you may be
-able to
-skip the no-op commit. Another possible reason for checking the flag is for
-efficient handling of JNI_ABORT. For example, you might want
-to get an array, modify it in place, pass pieces to other functions, and
-then discard the changes. If you know that JNI is making a new copy for
-you, there's no need to create another "editable" copy. If JNI is passing
-you the original, then you do need to make your own copy.
It is a common mistake (repeated in example code) to assume that you can skip the Release call if
-*isCopy is false. This is not the case. If no copy buffer was
-allocated, then the original memory must be pinned down and can't be moved by
-the garbage collector.
Also note that the JNI_COMMIT flag does not release the array,
-and you will need to call Release again with a different flag
-eventually.
There is an alternative to calls like Get<Type>ArrayElements
-and GetStringChars that may be very helpful when all you want
-to do is copy data in or out. Consider the following:
jbyte* data = env->GetByteArrayElements(array, NULL);
- if (data != NULL) {
- memcpy(buffer, data, len);
- env->ReleaseByteArrayElements(array, data, JNI_ABORT);
- }
-
-This grabs the array, copies the first len byte
-elements out of it, and then releases the array. Depending upon the
-implementation, the Get call will either pin or copy the array
-contents.
-The code copies the data (for perhaps a second time), then calls Release; in this case
-JNI_ABORT ensures there's no chance of a third copy.
One can accomplish the same thing more simply:
-env->GetByteArrayRegion(array, 0, len, buffer);- -
This has several advantages:
-Release after something fails.
-Similarly, you can use the Set<Type>ArrayRegion call
-to copy data into an array, and GetStringRegion or
-GetStringUTFRegion to copy characters out of a
-String.
-
-
-
-
You must not call most JNI functions while an exception is pending.
-Your code is expected to notice the exception (via the function's return value,
-ExceptionCheck, or ExceptionOccurred) and return,
-or clear the exception and handle it.
The only JNI functions that you are allowed to call while an exception is -pending are:
-DeleteGlobalRef
- DeleteLocalRef
- DeleteWeakGlobalRef
- ExceptionCheck
- ExceptionClear
- ExceptionDescribe
- ExceptionOccurred
- MonitorExit
- PopLocalFrame
- PushLocalFrame
- Release<PrimitiveType>ArrayElements
- ReleasePrimitiveArrayCritical
- ReleaseStringChars
- ReleaseStringCritical
- ReleaseStringUTFChars
-Many JNI calls can throw an exception, but often provide a simpler way
-of checking for failure. For example, if NewString returns
-a non-NULL value, you don't need to check for an exception. However, if
-you call a method (using a function like CallObjectMethod),
-you must always check for an exception, because the return value is not
-going to be valid if an exception was thrown.
Note that exceptions thrown by interpreted code do not unwind native stack
-frames, and Android does not yet support C++ exceptions.
-The JNI Throw and ThrowNew instructions just
-set an exception pointer in the current thread. Upon returning to managed
-from native code, the exception will be noted and handled appropriately.
Native code can "catch" an exception by calling ExceptionCheck or
-ExceptionOccurred, and clear it with
-ExceptionClear. As usual,
-discarding exceptions without handling them can lead to problems.
There are no built-in functions for manipulating the Throwable object
-itself, so if you want to (say) get the exception string you will need to
-find the Throwable class, look up the method ID for
-getMessage "()Ljava/lang/String;", invoke it, and if the result
-is non-NULL use GetStringUTFChars to get something you can
-hand to printf(3) or equivalent.
JNI does very little error checking. Errors usually result in a crash. Android also offers a mode called CheckJNI, where the JavaVM and JNIEnv function table pointers are switched to tables of functions that perform an extended series of checks before calling the standard implementation.
- -The additional checks include:
- -NewDirectByteBuffer.Call*Method JNI call: incorrect return type, static/non-static mismatch, wrong type for ‘this’ (for non-static calls) or wrong class (for static calls).DeleteGlobalRef/DeleteLocalRef on the wrong kind of reference.0, JNI_ABORT, or JNI_COMMIT).(Accessibility of methods and fields is still not checked: access restrictions don't apply to native code.)
- -There are several ways to enable CheckJNI.
- -If you’re using the emulator, CheckJNI is on by default.
- -If you have a rooted device, you can use the following sequence of commands to restart the runtime with CheckJNI enabled:
- -adb shell stop -adb shell setprop dalvik.vm.checkjni true -adb shell start- -
In either of these cases, you’ll see something like this in your logcat output when the runtime starts:
- -D AndroidRuntime: CheckJNI is ON- -
If you have a regular device, you can use the following command:
- -adb shell setprop debug.checkjni 1- -
This won’t affect already-running apps, but any app launched from that point on will have CheckJNI enabled. (Change the property to any other value or simply rebooting will disable CheckJNI again.) In this case, you’ll see something like this in your logcat output the next time an app starts:
- -D Late-enabling CheckJNI- - - - - -
You can load native code from shared libraries with the standard
-System.loadLibrary call. The
-preferred way to get at your native code is:
System.loadLibrary from a static class
-initializer. (See the earlier example, where one is used to call
-nativeClassInit.) The argument is the "undecorated"
-library name, so to load "libfubar.so" you would pass in "fubar".jint JNI_OnLoad(JavaVM* vm, void* reserved)JNI_OnLoad, register all of your native methods. You
-should declare
-the methods "static" so the names don't take up space in the symbol table
-on the device.The JNI_OnLoad function should look something like this if
-written in C++:
jint JNI_OnLoad(JavaVM* vm, void* reserved)
-{
- JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- return -1;
- }
-
- // Get jclass with env->FindClass.
- // Register methods with env->RegisterNatives.
-
- return JNI_VERSION_1_6;
-}
-
-You can also call System.load with the full path name of the
-shared library. For Android apps, you may find it useful to get the full
-path to the application's private data storage area from the context object.
This is the recommended approach, but not the only approach. Explicit
-registration is not required, nor is it necessary that you provide a
-JNI_OnLoad function.
-You can instead use "discovery" of native methods that are named in a
-specific way (see the JNI spec for details), though this is less desirable because if a method signature is wrong you won't know
-about it until the first time the method is actually used.
One other note about JNI_OnLoad: any FindClass
-calls you make from there will happen in the context of the class loader
-that was used to load the shared library. Normally FindClass
-uses the loader associated with the method at the top of the interpreted
-stack, or if there isn't one (because the thread was just attached) it uses
-the "system" class loader. This makes
-JNI_OnLoad a convenient place to look up and cache class
-object references.
Android is currently expected to run on 32-bit platforms. In theory it
-could be built for a 64-bit system, but that is not a goal at this time.
-For the most part this isn't something that you will need to worry about
-when interacting with native code,
-but it becomes significant if you plan to store pointers to native
-structures in integer fields in an object. To support architectures
-that use 64-bit pointers, you need to stash your native pointers in a
-long field rather than an int.
-
-
-
-
All JNI 1.6 features are supported, with the following exception:
-DefineClass is not implemented. Android does not use
- Java bytecodes or class files, so passing in binary class data
- doesn't work.For backward compatibility with older Android releases, you may need to -be aware of:
-Until Android 2.0 (Eclair), the '$' character was not properly - converted to "_00024" during searches for method names. Working - around this requires using explicit registration or moving the - native methods out of inner classes. -
Until Android 2.0 (Eclair), it was not possible to use a pthread_key_create
- destructor function to avoid the "thread must be detached before
- exit" check. (The runtime also uses a pthread key destructor function,
- so it'd be a race to see which gets called first.)
-
Until Android 2.2 (Froyo), weak global references were not implemented. - Older versions will vigorously reject attempts to use them. You can use - the Android platform version constants to test for support. -
Until Android 4.0 (Ice Cream Sandwich), weak global references could only
- be passed to NewLocalRef, NewGlobalRef, and
- DeleteWeakGlobalRef. (The spec strongly encourages
- programmers to create hard references to weak globals before doing
- anything with them, so this should not be at all limiting.)
-
From Android 4.0 (Ice Cream Sandwich) on, weak global references can be - used like any other JNI references.
Until Android 4.0 (Ice Cream Sandwich), local references were - actually direct pointers. Ice Cream Sandwich added the indirection - necessary to support better garbage collectors, but this means that lots - of JNI bugs are undetectable on older releases. See - JNI Local Reference Changes in ICS for more details. -
GetObjectRefType
- Until Android 4.0 (Ice Cream Sandwich), as a consequence of the use of
- direct pointers (see above), it was impossible to implement
- GetObjectRefType correctly. Instead we used a heuristic
- that looked through the weak globals table, the arguments, the locals
- table, and the globals table in that order. The first time it found your
- direct pointer, it would report that your reference was of the type it
- happened to be examining. This meant, for example, that if
- you called GetObjectRefType on a global jclass that happened
- to be the same as the jclass passed as an implicit argument to your static
- native method, you'd get JNILocalRefType rather than
- JNIGlobalRefType.
-
UnsatisfiedLinkError?When working on native code it's not uncommon to see a failure like this:
-java.lang.UnsatisfiedLinkError: Library foo not found- -
In some cases it means what it says — the library wasn't found. In
-other cases the library exists but couldn't be opened by dlopen(3), and
-the details of the failure can be found in the exception's detail message.
Common reasons why you might encounter "library not found" exceptions:
-adb shell ls -l <path> to check its presence
- and permissions.
- Another class of UnsatisfiedLinkError failures looks like:
java.lang.UnsatisfiedLinkError: myfunc - at Foo.myfunc(Native Method) - at Foo.main(Foo.java:10)- -
In logcat, you'll see:
-W/dalvikvm( 880): No implementation found for native LFoo;.myfunc ()V- -
This means that the runtime tried to find a matching method but was -unsuccessful. Some common reasons for this are:
-extern "C" and appropriate
- visibility (JNIEXPORT). Note that prior to Ice Cream
- Sandwich, the JNIEXPORT macro was incorrect, so using a new GCC with
- an old jni.h won't work.
- You can use arm-eabi-nm
- to see the symbols as they appear in the library; if they look
- mangled (something like _Z15Java_Foo_myfuncP7_JNIEnvP7_jclass
- rather than Java_Foo_myfunc), or if the symbol type is
- a lowercase 't' rather than an uppercase 'T', then you need to
- adjust the declaration.
- byte and 'Z' is boolean.
- Class name components in signatures start with 'L', end with ';',
- use '/' to separate package/class names, and use '$' to separate
- inner-class names (Ljava/util/Map$Entry;, say).
- Using javah to automatically generate JNI headers may help
-avoid some problems.
-
-
-
-
FindClass find my class?Make sure that the class name string has the correct format. JNI class
-names start with the package name and are separated with slashes,
-such as java/lang/String. If you're looking up an array class,
-you need to start with the appropriate number of square brackets and
-must also wrap the class with 'L' and ';', so a one-dimensional array of
-String would be [Ljava/lang/String;.
If the class name looks right, you could be running into a class loader
-issue. FindClass wants to start the class search in the
-class loader associated with your code. It examines the call stack,
-which will look something like:
-
Foo.myfunc(Native Method) - Foo.main(Foo.java:10) - dalvik.system.NativeStart.main(Native Method)- -
The topmost method is Foo.myfunc. FindClass
-finds the ClassLoader object associated with the Foo
-class and uses that.
This usually does what you want. You can get into trouble if you
-create a thread yourself (perhaps by calling pthread_create
-and then attaching it with AttachCurrentThread).
-Now the stack trace looks like this:
dalvik.system.NativeStart.run(Native Method)- -
The topmost method is NativeStart.run, which isn't part of
-your application. If you call FindClass from this thread, the
-JavaVM will start in the "system" class loader instead of the one associated
-with your application, so attempts to find app-specific classes will fail.
There are a few ways to work around this:
-FindClass lookups once, in
- JNI_OnLoad, and cache the class references for later
- use. Any FindClass calls made as part of executing
- JNI_OnLoad will use the class loader associated with
- the function that called System.loadLibrary (this is a
- special rule, provided to make library initialization more convenient).
- If your app code is loading the library, FindClass
- will use the correct class loader.
- Foo.class in.
- ClassLoader object somewhere
- handy, and issue loadClass calls directly. This requires
- some effort.
-You may find yourself in a situation where you need to access a large -buffer of raw data from both managed and native code. Common examples -include manipulation of bitmaps or sound samples. There are two -basic approaches.
- -You can store the data in a byte[]. This allows very fast
-access from managed code. On the native side, however, you're
-not guaranteed to be able to access the data without having to copy it. In
-some implementations, GetByteArrayElements and
-GetPrimitiveArrayCritical will return actual pointers to the
-raw data in the managed heap, but in others it will allocate a buffer
-on the native heap and copy the data over.
The alternative is to store the data in a direct byte buffer. These
-can be created with java.nio.ByteBuffer.allocateDirect, or
-the JNI NewDirectByteBuffer function. Unlike regular
-byte buffers, the storage is not allocated on the managed heap, and can
-always be accessed directly from native code (get the address
-with GetDirectBufferAddress). Depending on how direct
-byte buffer access is implemented, accessing the data from managed code
-can be very slow.
The choice of which to use depends on two factors:
-ByteBuffer might be unwise.)
-If there's no clear winner, use a direct byte buffer. Support for them -is built directly into JNI, and performance should improve in future releases.
diff --git a/docs/html/training/perf-tips.jd b/docs/html/training/perf-tips.jd deleted file mode 100644 index 33b4b870bf6e..000000000000 --- a/docs/html/training/perf-tips.jd +++ /dev/null @@ -1,433 +0,0 @@ -page.title=Performance Tips -@jd:body - -This document primarily covers micro-optimizations that can improve overall app performance -when combined, but it's unlikely that these changes will result in dramatic -performance effects. Choosing the right algorithms and data structures should always be your -priority, but is outside the scope of this document. You should use the tips in this document -as general coding practices that you can incorporate into your habits for general code -efficiency.
- -There are two basic rules for writing efficient code:
-One of the trickiest problems you'll face when micro-optimizing an Android -app is that your app is certain to be running on multiple types of -hardware. Different versions of the VM running on different -processors running at different speeds. It's not even generally the case -that you can simply say "device X is a factor F faster/slower than device Y", -and scale your results from one device to others. In particular, measurement -on the emulator tells you very little about performance on any device. There -are also huge differences between devices with and without a -JIT: the best -code for a device with a JIT is not always the best code for a device -without.
- -To ensure your app performs well across a wide variety of devices, ensure -your code is efficient at all levels and agressively optimize your performance.
- - -Object creation is never free. A generational garbage collector with per-thread allocation -pools for temporary objects can make allocation cheaper, but allocating memory -is always more expensive than not allocating memory.
- -As you allocate more objects in your app, you will force a periodic -garbage collection, creating little "hiccups" in the user experience. The -concurrent garbage collector introduced in Android 2.3 helps, but unnecessary work -should always be avoided.
- -Thus, you should avoid creating object instances you don't need to. Some -examples of things that can help:
- -A somewhat more radical idea is to slice up multidimensional arrays into -parallel single one-dimension arrays:
- -Generally speaking, avoid creating short-term temporary objects if you -can. Fewer objects created mean less-frequent garbage collection, which has -a direct impact on user experience.
- - - - -If you don't need to access an object's fields, make your method static. -Invocations will be about 15%-20% faster. -It's also good practice, because you can tell from the method -signature that calling the method can't alter the object's state.
- - - - - -Consider the following declaration at the top of a class:
- --static int intVal = 42; -static String strVal = "Hello, world!"; -- -
The compiler generates a class initializer method, called
-<clinit>, that is executed when the class is first used.
-The method stores the value 42 into intVal, and extracts a
-reference from the classfile string constant table for strVal.
-When these values are referenced later on, they are accessed with field
-lookups.
We can improve matters with the "final" keyword:
- --static final int intVal = 42; -static final String strVal = "Hello, world!"; -- -
The class no longer requires a <clinit> method,
-because the constants go into static field initializers in the dex file.
-Code that refers to intVal will use
-the integer value 42 directly, and accesses to strVal will
-use a relatively inexpensive "string constant" instruction instead of a
-field lookup.
Note: This optimization applies only to primitive types and
-{@link java.lang.String} constants, not arbitrary reference types. Still, it's good
-practice to declare constants static final whenever possible.
In native languages like C++ it's common practice to use getters
-(i = getCount()) instead of accessing the field directly (i
-= mCount). This is an excellent habit for C++ and is often practiced in other
-object oriented languages like C# and Java, because the compiler can
-usually inline the access, and if you need to restrict or debug field access
-you can add the code at any time.
However, this is a bad idea on Android. Virtual method calls are expensive, -much more so than instance field lookups. It's reasonable to follow -common object-oriented programming practices and have getters and setters -in the public interface, but within a class you should always access -fields directly.
- -Without a JIT, -direct field access is about 3x faster than invoking a -trivial getter. With the JIT (where direct field access is as cheap as -accessing a local), direct field access is about 7x faster than invoking a -trivial getter.
- -Note that if you're using ProGuard, -you can have the best of both worlds because ProGuard can inline accessors for you.
- - - - - -The enhanced for loop (also sometimes known as "for-each" loop) can be used
-for collections that implement the {@link java.lang.Iterable} interface and for arrays.
-With collections, an iterator is allocated to make interface calls
-to {@code hasNext()} and {@code next()}. With an {@link java.util.ArrayList},
-a hand-written counted loop is
-about 3x faster (with or without JIT), but for other collections the enhanced
-for loop syntax will be exactly equivalent to explicit iterator usage.
There are several alternatives for iterating through an array:
- -
-static class Foo {
- int mSplat;
-}
-
-Foo[] mArray = ...
-
-public void zero() {
- int sum = 0;
- for (int i = 0; i < mArray.length; ++i) {
- sum += mArray[i].mSplat;
- }
-}
-
-public void one() {
- int sum = 0;
- Foo[] localArray = mArray;
- int len = localArray.length;
-
- for (int i = 0; i < len; ++i) {
- sum += localArray[i].mSplat;
- }
-}
-
-public void two() {
- int sum = 0;
- for (Foo a : mArray) {
- sum += a.mSplat;
- }
-}
-
-
-zero() is slowest, because the JIT can't yet optimize away
-the cost of getting the array length once for every iteration through the
-loop.
one() is faster. It pulls everything out into local
-variables, avoiding the lookups. Only the array length offers a performance
-benefit.
two() is fastest for devices without a JIT, and
-indistinguishable from one() for devices with a JIT.
-It uses the enhanced for loop syntax introduced in version 1.5 of the Java
-programming language.
So, you should use the enhanced for loop by default, but consider a
-hand-written counted loop for performance-critical {@link java.util.ArrayList} iteration.
Tip: -Also see Josh Bloch's Effective Java, item 46.
- - - -Consider the following class definition:
- -
-public class Foo {
- private class Inner {
- void stuff() {
- Foo.this.doStuff(Foo.this.mValue);
- }
- }
-
- private int mValue;
-
- public void run() {
- Inner in = new Inner();
- mValue = 27;
- in.stuff();
- }
-
- private void doStuff(int value) {
- System.out.println("Value is " + value);
- }
-}
-
-What's important here is that we define a private inner class
-(Foo$Inner) that directly accesses a private method and a private
-instance field in the outer class. This is legal, and the code prints "Value is
-27" as expected.
The problem is that the VM considers direct access to Foo's
-private members from Foo$Inner to be illegal because
-Foo and Foo$Inner are different classes, even though
-the Java language allows an inner class to access an outer class' private
-members. To bridge the gap, the compiler generates a couple of synthetic
-methods:
-/*package*/ static int Foo.access$100(Foo foo) {
- return foo.mValue;
-}
-/*package*/ static void Foo.access$200(Foo foo, int value) {
- foo.doStuff(value);
-}
-
-The inner class code calls these static methods whenever it needs to
-access the mValue field or invoke the doStuff() method
-in the outer class. What this means is that the code above really boils down to
-a case where you're accessing member fields through accessor methods.
-Earlier we talked about how accessors are slower than direct field
-accesses, so this is an example of a certain language idiom resulting in an
-"invisible" performance hit.
If you're using code like this in a performance hotspot, you can avoid the -overhead by declaring fields and methods accessed by inner classes to have -package access, rather than private access. Unfortunately this means the fields -can be accessed directly by other classes in the same package, so you shouldn't -use this in public API.
- - - - -As a rule of thumb, floating-point is about 2x slower than integer on -Android-powered devices.
- -In speed terms, there's no difference between float and
-double on the more modern hardware. Space-wise, double
-is 2x larger. As with desktop machines, assuming space isn't an issue, you
-should prefer double to float.
Also, even for integers, some processors have hardware multiply but lack -hardware divide. In such cases, integer division and modulus operations are -performed in software—something to think about if you're designing a -hash table or doing lots of math.
- - - - -In addition to all the usual reasons to prefer library code over rolling -your own, bear in mind that the system is at liberty to replace calls -to library methods with hand-coded assembler, which may be better than the -best code the JIT can produce for the equivalent Java. The typical example -here is {@link java.lang.String#indexOf String.indexOf()} and -related APIs, which Dalvik replaces with -an inlined intrinsic. Similarly, the {@link java.lang.System#arraycopy -System.arraycopy()} method -is about 9x faster than a hand-coded loop on a Nexus One with the JIT.
- - -Tip: -Also see Josh Bloch's Effective Java, item 47.
- - - - -Developing your app with native code using the -Android NDK -isn't necessarily more efficient than programming with the -Java language. For one thing, -there's a cost associated with the Java-native transition, and the JIT can't -optimize across these boundaries. If you're allocating native resources (memory -on the native heap, file descriptors, or whatever), it can be significantly -more difficult to arrange timely collection of these resources. You also -need to compile your code for each architecture you wish to run on (rather -than rely on it having a JIT). You may even have to compile multiple versions -for what you consider the same architecture: native code compiled for the ARM -processor in the G1 can't take full advantage of the ARM in the Nexus One, and -code compiled for the ARM in the Nexus One won't run on the ARM in the G1.
- -Native code is primarily useful when you have an existing native codebase -that you want to port to Android, not for "speeding up" parts of your Android app -written with the Java language.
- -If you do need to use native code, you should read our -JNI Tips.
- -Tip: -Also see Josh Bloch's Effective Java, item 54.
- - - - - -On devices without a JIT, it is true that invoking methods via a
-variable with an exact type rather than an interface is slightly more
-efficient. (So, for example, it was cheaper to invoke methods on a
-HashMap map than a Map map, even though in both
-cases the map was a HashMap.) It was not the case that this
-was 2x slower; the actual difference was more like 6% slower. Furthermore,
-the JIT makes the two effectively indistinguishable.
On devices without a JIT, caching field accesses is about 20% faster than -repeatedly accesssing the field. With a JIT, field access costs about the same -as local access, so this isn't a worthwhile optimization unless you feel it -makes your code easier to read. (This is true of final, static, and static -final fields too.) - - - -
Before you start optimizing, make sure you have a problem that you -need to solve. Make sure you can accurately measure your existing performance, -or you won't be able to measure the benefit of the alternatives you try.
- -Every claim made in this document is backed up by a benchmark. The source -to these benchmarks can be found in the code.google.com -"dalvik" project.
- -The benchmarks are built with the -Caliper microbenchmarking -framework for Java. Microbenchmarks are hard to get right, so Caliper goes out -of its way to do the hard work for you, and even detect some cases where you're -not measuring what you think you're measuring (because, say, the VM has -managed to optimize all your code away). We highly recommend you use Caliper -to run your own microbenchmarks.
- -You may also find -Traceview useful -for profiling, but it's important to realize that it currently disables the JIT, -which may cause it to misattribute time to code that the JIT may be able to win -back. It's especially important after making changes suggested by Traceview -data to ensure that the resulting code actually runs faster when run without -Traceview.
- -For more help profiling and debugging your apps, see the following documents:
- - - diff --git a/docs/html/training/security-tips.jd b/docs/html/training/security-tips.jd deleted file mode 100644 index 88d6017d670d..000000000000 --- a/docs/html/training/security-tips.jd +++ /dev/null @@ -1,759 +0,0 @@ -page.title=Security Tips -@jd:body - -Android has security features built -into the operating system that significantly reduce the frequency and impact of -application security issues. The system is designed so you can typically build your apps with -default system and file permissions and avoid difficult decisions about security.
- -Some of the core security features that help you build secure apps -include: -
Nevertheless, it is important that you be familiar with the Android -security best practices in this document. Following these practices as general coding habits -will reduce the likelihood of inadvertently introducing security issues that -adversely affect your users.
- - - -The most common security concern for an application on Android is whether the data -that you save on the device is accessible to other apps. There are three fundamental -ways to save data on the device:
- -By default, files that you create on internal -storage are accessible only to your app. This -protection is implemented by Android and is sufficient for most -applications.
- -You should generally avoid using the {@link android.content.Context#MODE_WORLD_WRITEABLE} or -{@link android.content.Context#MODE_WORLD_READABLE} modes for -IPC files because they do not provide -the ability to limit data access to particular applications, nor do they -provide any control on data format. If you want to share your data with other -app processes, you might instead consider using a -content provider, which -offers read and write permissions to other apps and can make -dynamic permission grants on a case-by-case basis.
- -To provide additional protection for sensitive data, you might -choose to encrypt local files using a key that is not directly accessible to the -application. For example, a key can be placed in a {@link java.security.KeyStore} -and protected with a user password that is not stored on the device. While this -does not protect data from a root compromise that can monitor the user -inputting the password, it can provide protection for a lost device without file system -encryption.
- - -Files created on external -storage, such as SD Cards, are globally readable and writable. Because -external storage can be removed by the user and also modified by any -application, you should not store sensitive information using -external storage.
- -As with data from any untrusted source, you should perform input -validation when handling data from external storage. -We strongly recommend that you not store executables or -class files on external storage prior to dynamic loading. If your app -does retrieve executable files from external storage, the files should be signed and -cryptographically verified prior to dynamic loading.
- - -Content providers
-offer a structured storage mechanism that can be limited
-to your own application or exported to allow access by other applications.
-If you do not intend to provide other
-applications with access to your {@link android.content.ContentProvider}, mark them as
-android:exported=false in the application manifest. Otherwise, set the android:exported
-attribute {@code "true"} to allow other apps to access the stored data.
-
When creating a {@link android.content.ContentProvider} -that will be exported for use by other applications, you can specify a single -permission - for reading and writing, or distinct permissions for reading and writing -within the manifest. We recommend that you limit your permissions to those -required to accomplish the task at hand. Keep in mind that it’s usually -easier to add permissions later to expose new functionality than it is to take -them away and break existing users.
- -If you are using a content provider -for sharing data between only your own apps, it is preferable to use the -{@code -android:protectionLevel} attribute set to {@code "signature"} protection. -Signature permissions do not require user confirmation, -so they provide a better user experience and more controlled access to the -content provider data when the apps accessing the data are -signed with -the same key.
- -Content providers can also provide more granular access by declaring the {@code
-android:grantUriPermissions} attribute and using the {@link
-android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} and {@link
-android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} flags in the
-{@link android.content.Intent} object
-that activates the component. The scope of these permissions can be further
-limited by the
-<grant-uri-permission element>.
When accessing a content provider, use parameterized query methods such as
-{@link android.content.ContentProvider#query(Uri,String[],String,String[],String) query()},
-{@link android.content.ContentProvider#update(Uri,ContentValues,String,String[]) update()}, and
-{@link android.content.ContentProvider#delete(Uri,String,String[]) delete()} to avoid
-potential SQL injection from untrusted sources. Note that using parameterized methods is not
-sufficient if the selection argument is built by concatenating user data
-prior to submitting it to the method.
Do not have a false sense of security about the write permission. Consider
-that the write permission allows SQL statements which make it possible for some
-data to be confirmed using creative WHERE clauses and parsing the
-results. For example, an attacker might probe for presence of a specific phone
-number in a call-log by modifying a row only if that phone number already
-exists. If the content provider data has predictable structure, the write
-permission may be equivalent to providing both reading and writing.
Because Android sandboxes applications from each other, applications must explicitly -share resources and data. They do this by declaring the permissions they need for additional -capabilities not provided by the basic sandbox, including access to device features such as -the camera.
- - -We recommend minimizing the number of permissions that your app requests -Not having access to sensitive permissions reduces the risk of -inadvertently misusing those permissions, can improve user adoption, and makes -your app less for attackers. Generally, -if a permission is not required for your app to function, do not request it.
- -If it's possible to design your application in a way that does not require -any permissions, that is preferable. For example, rather than requesting access -to device information to create a unique identifier, create a GUID for your application -(see the section about Handling User Data). Or, rather than -using external storage (which requires permission), store data -on the internal storage.
- -In addition to requesting permissions, your application can use the {@code <permissions>} -to protect IPC that is security sensitive and will be exposed to other -applications, such as a {@link android.content.ContentProvider}. -In general, we recommend using access controls -other than user confirmed permissions where possible because permissions can -be confusing for users. For example, consider using the signature -protection level on permissions for IPC communication between applications -provided by a single developer.
- -Do not leak permission-protected data. This occurs when your app exposes data -over IPC that is only available because it has a specific permission, but does -not require that permission of any clients of it’s IPC interface. More -details on the potential impacts, and frequency of this type of problem is -provided in this research paper published at USENIX: http://www.cs.be -rkeley.edu/~afelt/felt_usenixsec2011.pdf
- - - -Generally, you should strive to define as few permissions as possible while -satisfying your security requirements. Creating a new permission is relatively -uncommon for most applications, because the system-defined -permissions cover many situations. Where appropriate, -perform access checks using existing permissions.
- -If you must create a new permission, consider whether you can accomplish -your task with a "signature" -protection level. Signature permissions are transparent -to the user and only allow access by applications signed by the same developer -as application performing the permission check.
- -If you create a permission with the "dangerous" -protection level, there are a number of complexities -that you need to consider: -
Each of these poses a significant non-technical challenge for you as the developer -while also confusing your users, -which is why we discourage the use of the "dangerous" permission level.
- - - - - -Network transactions are inherently risky for security, because it involves transmitting -data that is potentially private to the user. People are increasingly aware of the privacy -concerns of a mobile device, especially when the device performs network transactions, -so it's very important that your app implement all best practices toward keeping the user's -data secure at all times.
- -Networking on Android is not significantly different from other Linux -environments. The key consideration is making sure that appropriate protocols -are used for sensitive data, such as {@link javax.net.ssl.HttpsURLConnection} for -secure web traffic. We prefer use of HTTPS over HTTP anywhere that HTTPS is -supported on the server, because mobile devices frequently connect on networks -that are not secured, such as public Wi-Fi hotspots.
- -Authenticated, encrypted socket-level communication can be easily -implemented using the {@link javax.net.ssl.SSLSocket} -class. Given the frequency with which Android devices connect to unsecured -wireless networks using Wi-Fi, the use of secure networking is strongly -encouraged for all applications that communicate over the network.
- -We have seen some applications use localhost network ports for -handling sensitive IPC. We discourage this approach since these interfaces are -accessible by other applications on the device. Instead, you should use an Android IPC -mechanism where authentication is possible such as with a {@link android.app.Service}. (Even -worse than using loopback is to bind to INADDR_ANY since then your application -may receive requests from anywhere.)
- -Also, one common issue that warrants repeating is to make sure that you do -not trust data downloaded from HTTP or other insecure protocols. This includes -validation of input in {@link android.webkit.WebView} and -any responses to intents issued against HTTP.
- - -The SMS protocol was primarily designed for -user-to-user communication and is not well-suited for apps that want to transfer data. -Due to the limitations of SMS, we strongly recommend the use of Google Cloud Messaging (GCM) -and IP networking for sending data messages from a web server to your app on a user device.
- -Beware that SMS is neither encrypted nor strongly -authenticated on either the network or the device. In particular, any SMS receiver -should expect that a malicious user may have sent the SMS to your application—Do -not rely on unauthenticated SMS data to perform sensitive commands. -Also, you should be aware that SMS may be subject to spoofing and/or -interception on the network. On the Android-powered device itself, SMS -messages are transmitted as broadcast intents, so they may be read or captured -by other applications that have the {@link android.Manifest.permission#READ_SMS} -permission.
- - - - - -Insufficient input validation is one of the most common security problems -affecting applications, regardless of what platform they run on. Android does -have platform-level countermeasures that reduce the exposure of applications to -input validation issues and you should use those features where possible. Also -note that selection of type-safe languages tends to reduce the likelihood of -input validation issues.
- -If you are using native code, then any data read from files, received over -the network, or received from an IPC has the potential to introduce a security -issue. The most common problems are buffer overflows, use after -free, and off-by-one errors. -Android provides a number of technologies like ASLR and DEP that reduce the -exploitability of these errors, but they do not solve the underlying problem. -You can prevent these vulneratbilities by careful handling pointers and managing -buffers.
- -Dynamic, string based languages such as JavaScript and SQL are also subject -to input validation problems due to escape characters and script injection.
- -If you are using data within queries that are submitted to an SQL database or a -content provider, SQL injection may be an issue. The best defense is to use -parameterized queries, as is discussed in the above section about content providers. -Limiting permissions to read-only or write-only can also reduce the potential -for harm related to SQL injection.
- -If you cannot use the security features above, we strongly recommend the use -of well-structured data formats and verifying that the data conforms to the -expected format. While blacklisting of characters or character-replacement can -be an effective strategy, these techniques are error-prone in practice and -should be avoided when possible.
- - - - - -In general, the best approach for user data security is to minimize the use of APIs that access -sensitive or personal user data. If you have access to user data and can avoid -storing or transmitting the information, do not store or transmit the data. -Finally, consider if there is a way that your application logic can be -implemented using a hash or non-reversible form of the data. For example, your -application might use the hash of an an email address as a primary key, to -avoid transmitting or storing the email address. This reduces the chances of -inadvertently exposing data, and it also reduces the chance of attackers -attempting to exploit your application.
- -If your application accesses personal information such as passwords or -usernames, keep in mind that some jurisdictions may require you to provide a -privacy policy explaining your use and storage of that data. So following the -security best practice of minimizing access to user data may also simplify -compliance.
- -You should also consider whether your application might be inadvertently -exposing personal information to other parties such as third-party components -for advertising or third-party services used by your application. If you don't -know why a component or service requires a personal information, don’t -provide it. In general, reducing the access to personal information by your -application will reduce the potential for problems in this area.
- -If access to sensitive data is required, evaluate whether that information -must be transmitted to a server, or whether the operation can be performed on -the client. Consider running any code using sensitive data on the client to -avoid transmitting user data.
- -Also, make sure that you do not inadvertently expose user data to other -application on the device through overly permissive IPC, world writable files, -or network sockets. This is a special case of leaking permission-protected data, -discussed in the Requesting Permissions section.
- -If a GUID -is required, create a large, unique number and store it. Do not -use phone identifiers such as the phone number or IMEI which may be associated -with personal information. This topic is discussed in more detail in the Android -Developer Blog.
- -Be careful when writing to on-device logs. -In Android, logs are a shared resource, and are available -to an application with the {@link android.Manifest.permission#READ_LOGS} permission. -Even though the phone log data -is temporary and erased on reboot, inappropriate logging of user information -could inadvertently leak user data to other applications.
- - - - - - -Because {@link android.webkit.WebView} consumes web content that can include HTML and JavaScript, -improper use can introduce common web security issues such as cross-site-scripting -(JavaScript injection). Android includes a number of mechanisms to reduce -the scope of these potential issues by limiting the capability of {@link android.webkit.WebView} to -the minimum functionality required by your application.
- -If your application does not directly use JavaScript within a {@link android.webkit.WebView}, do -not call {@link android.webkit.WebSettings#setJavaScriptEnabled setJavaScriptEnabled()}. -Some sample code uses this method, which you might repurpose in production -application, so remove that method call if it's not required. By default, -{@link android.webkit.WebView} does -not execute JavaScript so cross-site-scripting is not possible.
- -Use {@link android.webkit.WebView#addJavascriptInterface -addJavaScriptInterface()} with -particular care because it allows JavaScript to invoke operations that are -normally reserved for Android applications. If you use it, expose -{@link android.webkit.WebView#addJavascriptInterface addJavaScriptInterface()} only to -web pages from which all input is trustworthy. If untrusted input is allowed, -untrusted JavaScript may be able to invoke Android methods within your app. In general, we -recommend exposing {@link android.webkit.WebView#addJavascriptInterface -addJavaScriptInterface()} only to JavaScript that is contained within your application APK.
- -If your application accesses sensitive data with a
-{@link android.webkit.WebView}, you may want to use the
-{@link android.webkit.WebView#clearCache clearCache()} method to delete any files stored
-locally. Server-side
-headers like no-cache can also be used to indicate that an application should
-not cache particular content.
In general, we recommend minimizing the frequency of asking for user -credentials—to make phishing attacks more conspicuous, and less likely to be -successful. Instead use an authorization token and refresh it.
- -Where possible, username and password should not be stored on the device. -Instead, perform initial authentication using the username and password -supplied by the user, and then use a short-lived, service-specific -authorization token.
- -Services that will be accessible to multiple applications should be accessed -using {@link android.accounts.AccountManager}. If possible, use the -{@link android.accounts.AccountManager} class to invoke a cloud-based service and do not store -passwords on the device.
- -After using {@link android.accounts.AccountManager} to retrieve an -{@link android.accounts.Account}, {@link android.accounts.Account#CREATOR} -before passing in any credentials, so that you do not inadvertently pass -credentials to the wrong application.
- -If credentials are to be used only by applications that you create, then you -can verify the application which accesses the {@link android.accounts.AccountManager} using -{@link android.content.pm.PackageManager#checkSignatures checkSignature()}. -Alternatively, if only one application will use the credential, you might use a -{@link java.security.KeyStore} for storage.
- - - - - -In addition to providing data isolation, supporting full-filesystem -encryption, and providing secure communications channels, Android provides a -wide array of algorithms for protecting data using cryptography.
- -In general, try to use the highest level of pre-existing framework -implementation that can support your use case. If you need to securely -retrieve a file from a known location, a simple HTTPS URI may be adequate and -requires no knowledge of cryptography. If you need a secure -tunnel, consider using {@link javax.net.ssl.HttpsURLConnection} or -{@link javax.net.ssl.SSLSocket}, rather than writing your own protocol.
- -If you do find yourself needing to implement your own protocol, we strongly -recommend that you not implement your own cryptographic algorithms. Use -existing cryptographic algorithms such as those in the implementation of AES or -RSA provided in the {@link javax.crypto.Cipher} class.
- -Use a secure random number generator, {@link java.security.SecureRandom}, -to initialize any cryptographic keys, {@link javax.crypto.KeyGenerator}. -Use of a key that is not generated with a secure random -number generator significantly weakens the strength of the algorithm, and may -allow offline attacks.
- -If you need to store a key for repeated use, use a mechanism like - {@link java.security.KeyStore} that -provides a mechanism for long term storage and retrieval of cryptographic -keys.
- - - - - -Some apps attempt to implement IPC using traditional Linux -techniques such as network sockets and shared files. We strongly encourage you to instead -use Android system functionality for IPC such as {@link android.content.Intent}, -{@link android.os.Binder} or {@link android.os.Messenger} with a {@link -android.app.Service}, and {@link android.content.BroadcastReceiver}. -The Android IPC mechanisms allow you to verify the identity of -the application connecting to your IPC and set security policy for each IPC -mechanism.
- -Many of the security elements are shared across IPC mechanisms. -If your IPC mechanism is not intended for use by other applications, set the -{@code android:exported} attribute to {@code "false"} in the component's manifest element, -such as for the {@code <service>} -element. This is useful for applications that consist of multiple processes -within the same UID, or if you decide late in development that you do not -actually want to expose functionality as IPC but you don’t want to rewrite -the code.
- -If your IPC is intended to be accessible to other applications, you can -apply a security policy by using the {@code <permission>} -element. If IPC is between your own separate apps that are signed with the same key, -it is preferable to use {@code "signature"} level permission in the {@code -android:protectionLevel}.
- - - - -Intents are the preferred mechanism for asynchronous IPC in Android. -Depending on your application requirements, you might use {@link -android.content.Context#sendBroadcast sendBroadcast()}, {@link -android.content.Context#sendOrderedBroadcast sendOrderedBroadcast()}, -or an explicit intent to a specific application component.
- -Note that ordered broadcasts can be “consumed” by a recipient, so they -may not be delivered to all applications. If you are sending an intent that muse be delivered -to a specific receiver, then you must use an explicit intent that declares the receiver -by nameintent.
- -Senders of an intent can verify that the recipient has a permission -specifying a non-Null permission with the method call. Only applications with that -permission will receive the intent. If data within a broadcast intent may be -sensitive, you should consider applying a permission to make sure that -malicious applications cannot register to receive those messages without -appropriate permissions. In those circumstances, you may also consider -invoking the receiver directly, rather than raising a broadcast.
- -Note: Intent filters should not be considered -a security feature—components -can be invoked with explicit intents and may not have data that would conform to the intent -filter. You should perform input validation within your intent receiver to -confirm that it is properly formatted for the invoked receiver, service, or -activity.
- - - - -A {@link android.app.Service} is often used to supply functionality for other applications to
-use. Each service class must have a corresponding {@code
By default, services are not exported and cannot be invoked by any other
-application. However, if you add any intent filters to the service declaration, then it is exported
-by default. It's best if you explicitly declare the {@code
-android:exported} attribute to be sure it behaves as you'd like.
-Services can also be protected using the {@code android:permission}
-attribute. By doing so, other applications will need to declare
-a corresponding <uses-permission>
- element in their own manifest to be
-able to start, stop, or bind to the service.
A service can protect individual IPC calls into it with permissions, by -calling {@link android.content.Context#checkCallingPermission -checkCallingPermission()} before executing -the implementation of that call. We generally recommend using the -declarative permissions in the manifest, since those are less prone to -oversight.
- - - -Using {@link android.os.Binder} or {@link android.os.Messenger} is the -preferred mechanism for RPC-style IPC in Android. They provide a well-defined -interface that enables mutual authentication of the endpoints, if required.
- -We strongly encourage designing interfaces in a manner that does not require -interface specific permission checks. {@link android.os.Binder} and -{@link android.os.Messenger} objects are not declared within the -application manifest, and therefore you cannot apply declarative permissions -directly to them. They generally inherit permissions declared in the -application manifest for the {@link android.app.Service} or {@link -android.app.Activity} within which they are -implemented. If you are creating an interface that requires authentication -and/or access controls, those controls must be -explicitly added as code in the {@link android.os.Binder} or {@link android.os.Messenger} -interface.
- -If providing an interface that does require access controls, use {@link -android.content.Context#checkCallingPermission checkCallingPermission()} -to verify whether the -caller has a required permission. This is especially important -before accessing a service on behalf of the caller, as the identify of your -application is passed to other interfaces. If invoking an interface provided -by a {@link android.app.Service}, the {@link -android.content.Context#bindService bindService()} - invocation may fail if you do not have permission to access the given service. - If calling an interface provided locally by your own application, it may be -useful to use the {@link android.os.Binder#clearCallingIdentity clearCallingIdentity()} -to satisfy internal security checks.
- -For more information about performing IPC with a service, see -Bound Services.
- - - -A {@link android.content.BroadcastReceiver} handles asynchronous requests initiated by -an {@link android.content.Intent}.
- -By default, receivers are exported and can be invoked by any other
-application. If your {@link android.content.BroadcastReceiver}
-is intended for use by other applications, you
-may want to apply security permissions to receivers using the
-<receiver> element within the application manifest. This will
-prevent applications without appropriate permissions from sending an intent to
-the {@link android.content.BroadcastReceiver}.
We strongly discourage loading code from outside of your application APK. -Doing so significantly increases the likelihood of application compromise due -to code injection or code tampering. It also adds complexity around version -management and application testing. Finally, it can make it impossible to -verify the behavior of an application, so it may be prohibited in some -environments.
- -If your application does dynamically load code, the most important thing to -keep in mind about dynamically loaded code is that it runs with the same -security permissions as the application APK. The user made a decision to -install your application based on your identity, and they are expecting that -you provide any code run within the application, including code that is -dynamically loaded.
- -The major security risk associated with dynamically loading code is that the -code needs to come from a verifiable source. If the modules are included -directly within your APK, then they cannot be modified by other applications. -This is true whether the code is a native library or a class being loaded using -{@link dalvik.system.DexClassLoader}. We have seen many instances of applications -attempting to load code from insecure locations, such as downloaded from the -network over unencrypted protocols or from world writable locations such as -external storage. These locations could allow someone on the network to modify -the content in transit, or another application on a users device to modify the -content on the device, respectively.
- - - - - -Dalvik is Android's runtime virtual machine (VM). Dalvik was built specifically for Android, -but many of the concerns regarding secure code in other virtual machines also apply to Android. -In general, you shouldn't concern yourself with security issues relating to the virtual machine. -Your application runs in a secure sandbox environment, so other processes on the system cannnot -access your code or private data.
- -If you're interested in diving deeper on the subject of virtual machine security, -we recommend that you familiarize yourself with some -existing literature on the subject. Two of the more popular resources are: -
This document is focused on the areas which are Android specific or -different from other VM environments. For developers experienced with VM -programming in other environments, there are two broad issues that may be -different about writing apps for Android: -
In general, we encourage developers to use the Android SDK for -application development, rather than using native code with the -Android NDK. Applications built -with native code are more complex, less portable, and more like to include -common memory corruption errors such as buffer overflows.
- -Android is built using the Linux kernel and being familiar with Linux -development security best practices is especially useful if you are going to -use native code. Linux security practices are beyond the scope of this document, -but one of the most popular resources is “Secure Programming for -Linux and Unix HOWTO”, available at -http://www.dwheeler.com/secure-programs.
- -An important difference between Android and most Linux environments is the -Application Sandbox. On Android, all applications run in the Application -Sandbox, including those written with native code. At the most basic level, a -good way to think about it for developers familiar with Linux is to know that -every application is given a unique UID -with very limited permissions. This is discussed in more detail in the Android Security -Overview and you should be familiar with application permissions even if -you are using native code.
- diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index ece55823e44c..abce37a2eea6 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -775,7 +775,7 @@