summaryrefslogtreecommitdiffstats
path: root/runtime/dex_file.cc
Commit message (Collapse)AuthorAgeFilesLines
* Add hash map, reduce excessive hashingMathieu Chartier2014-11-071-4/+5
| | | | | | | | | | | | | | | | | | | | | | | Changed the class def index to use a HashMap instead of unordered_map so that we can use FindWithHash to reduce how often we need to compute hashes. Fixed a bug in ClassLinker::UpdateClass where we didn't properly handle classes with the same descriptor but different class loaders. Introduced by previous CL. Before (fb launch): 1.74% art::ComputeModifiedUtf8Hash(char const*) After: 0.95% art::ComputeModifiedUtf8Hash(char const*) Bug: 18054905 Bug: 16828525 Change-Id: Iba2ee37c9837289e0ea187800ba4af322225a994 (cherry picked from commit 564ff985184737977aa26c485d0c1a413e530705)
* ART: More warningsAndreas Gampe2014-11-041-3/+7
| | | | | | | Enable -Wno-conversion-null, -Wredundant-decls and -Wshadow in general, and -Wunused-but-set-parameter for GCC builds. Change-Id: I81bbdd762213444673c65d85edae594a523836e5
* Tidy logging code not using UNIMPLEMENTED.Ian Rogers2014-10-241-1/+2
| | | | Change-Id: I7a79c1671a6ff8b2040887133b3e0925ef9a3cfe
* Tidy up logging.Ian Rogers2014-10-221-0/+2
| | | | | | | | | | | | | | | | | Move gVerboseMethods to CompilerOptions. Now "--verbose-methods=" option to dex2oat rather than runtime argument "-verbose-methods:". Move ToStr and Dumpable out of logging.h, move LogMessageData into logging.cc except for a forward declaration. Remove ConstDumpable as Dump methods are all const (and make this so if not currently true). Make LogSeverity an enum and improve compile time assertions and type checking. Remove log_severity.h that's only used in logging.h. With system headers gone from logging.h, go add to .cc files missing system header includes. Also, make operator new in ValueObject private for compile time instantiation checking. Change-Id: I3228f614500ccc9b14b49c72b9821c8b0db3d641
* stdint types all the way!Ian Rogers2014-10-091-16/+16
| | | | Change-Id: I4e4ef3a2002fc59ebd9097087f150eaf3f2a7e08
* Remove dex file index building mutex.Ian Rogers2014-09-121-14/+14
| | | | | | | | First thread to get to max misses builds the index and sets an atomic, other threads continue and return null. Avoids lock contention and removes a member variable. Change-Id: Ia91e4a8fd915941aea849f019c85b67894ec6e71
* Merge "ART: Fix things for valgrind"Andreas Gampe2014-09-101-5/+6
|\
| * ART: Fix things for valgrindAndreas Gampe2014-09-101-5/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Wire up valgrind gtests. Add valgrind-test-art-host, currently only depending on valgrind-test-art-host-gtest32. Fix an Alloc setting to allow running valgrind. Refactor the fault handler to manage (and correctly release) the handlers. Fix minor failure-case leaks exposed by tests. Failing tests: The optimizing compiler is leaking non-arena-ed structures (e.g., assembler buffers), as code generators are not destroyed. The solution has been moved to a follow-up CL. Note: All 64b tests are failing as we cannot allocate a heap. Change-Id: I7f854cfd098d9f68107ce492363e7dba9a82b9fa
* | Improve dex location canonicalization-related performance.Vladimir Marko2014-09-101-41/+16
|/ | | | | | | | | | | | | | | | | | | Eagerly add canonical dex file locations to the OatFile's primary lookup map in Setup(). This moves the boot.oat work from every app startup to the zygote initialization. Since we always ended up initializing the canonical location map anyway due to the way that we're loading dex files, the lazy initialization didn't save anything. Clean up dex file name canonicalization to make sure we free() the memory returned by realpath() rather than using std::unique_ptr<> with the default deleter. Avoid some unnecessary duplicate OatDexFile lookups. Bug: 16828525 Bug: 17346103 Change-Id: Id8fbc8992f62996138eb2006a0046c6529747c09
* Reduce and speed-up class def searches.Ian Rogers2014-09-021-29/+45
| | | | | | | | | | | | | | | | | | | | Use the class linker for descriptor lookups from the compile driver so that dex caches are populated. Reduce the scope of functions for scanning class paths to just the class linker where they are performed. If we see more than a threshold number of find class def misses on a dex file lazily compute an index, so that future lookups are constant time (part of the collection code is taken from https://android-review.googlesource.com/#/c/103865/3). Note that we take a lazy approach so that we don't serialize on loading dex files, this avoids the reason the index was removed in 8b2c0b9abc3f520495f4387ea040132ba85cae69. Remove an implicit and unnecessary std::string creation for PrintableString. Single threaded interpret-only dex2oat performance is improved by roughly 10%. Bug: 16853450 Change-Id: Icf72df76b0a4328f2a24075e81f4ff267b9401f4
* Avoid handle-less fields in ClassLinker::InitializeClass()Hiroshi Yamauchi2014-08-211-3/+3
| | | | | | | There were some handle-less fields in a SafeMap across GC points. Bug: 12687968 Change-Id: Ib8c6527d4e23031f1d0074fa11d8f85499b68340
* Remove clang detected warning on tautological comparisonBrian Carlstrom2014-08-081-1/+0
| | | | | Bug: 16903117 Change-Id: I5847ef5a6091c01e14b9ffcd8f6d12cabfa8b63b
* Use canonical paths when searching for dex filesCalin Juravle2014-08-041-0/+33
| | | | | | | | | | | | Apps which use the DexPathClassLoader directly may pass symlinks when trying to load dex files. This will not work as we use string comparision to find the dex in an oat file. The CL fixes this issue by using using dex conical paths for comparisons. Bug: 15313272 Change-Id: Ic314374b17612c3afbcadec93a88b2515a0aca5e
* Return "false" instead of "nullptr" in bool DexFile::Open.Alexander Ivchenko2014-06-261-1/+1
| | | | | | | | | | Otherwise on 4.10 the following error appears: "error: converting to 'bool' from 'std::nullptr_t' requires direct-initialization [-fpermissive]" Here is the detailed description with links: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52174 Change-Id: I77c6571b557dde55f4e19a79db7bf997303ede3b Signed-off-by: Alexander Ivchenko <alexander.ivchenko@intel.com>
* ART: Native support for multidexAndreas Gampe2014-06-251-19/+105
| | | | | | | | | | | | | | | | | | | | Native support for zip files with multiple classesX.dex. Works by explicitly looking for those files in ascending order. As these files have no file system representation for themselves, introduce synthetic dex locations: the name of the originating file plus a colon plus the name of the dex file, e.g., test.jar:classes2.dex. Opening a zip dex file will return all dex files in this way. This keeps the changes to dex2oat minimal. To hide multidex/synthetic names from the Java layer, let the handle of dalvik.system.DexFile refer to a vector of DexFile objects. When opening a location, test possible synthetic names and add them to the vector. Thus, the original multidex jar in the classpath will be associated with all embedded dex files. Change-Id: I0de107e1369cbc94416c544aca3b17525c9eac8b
* ART: Do not try to pretty-print method in dex fileAndreas Gampe2014-06-191-4/+2
| | | | | | | | The code is called in verification when it is not clear yet whether structures are valid. Simplify warning message. Bug: 15754233 Change-Id: I85858a71143f41444ce9f00536d901c268afe547
* Make DexFile content read only before running DexFileVerifierBrian Carlstrom2014-05-251-4/+4
| | | | | | (cherry picked from commit 98725444129efe2b1b51c87740860caadaef2bf7) Change-Id: I18a932b2f19d44b820232f4d4e9c358df20ab364
* Fix ExtractToMemMap to show original zip file name in ashmemBrian Carlstrom2014-05-231-1/+1
| | | | | | (cherry picked from commit 1fca8e91f32dc8b13d3129b7ef4a0194839736e6) Change-Id: Id7d22600496b090ac32150c8c6424da89964b6be
* Now we have a proper C++ library, use std::unique_ptr.Ian Rogers2014-05-191-11/+11
| | | | | | | Also remove the Android.libcxx.mk and other bits of stlport compatibility mechanics. Change-Id: Icdf7188ba3c79cdf5617672c1cfd0a68ae596a61
* Compatibility layer to transition from UniquePtr to std::unique_ptr.Ian Rogers2014-05-151-1/+1
| | | | | | | | | Use ART_WITH_STLPORT (enabled for the target) to cause the use of UniquePtr, for the host switch to std::unique_ptr. For now the type remains called UniquePtr. Make dalvik compile with clang on the host, move its build to C++11. Change-Id: I5ba8d2757904bc089ed62047ea03de3c0853fb12
* Add Handle/HandleScope and delete SirtRef.Mathieu Chartier2014-05-131-3/+3
| | | | | | | | | | | | | | | | Delete SirtRef and replaced it with Handle. Handles are value types which wrap around StackReference*. Renamed StackIndirectReferenceTable to HandleScope. Added a scoped handle wrapper which wraps around an Object** and restores it in its destructor. Renamed Handle::get -> Get. Bug: 8473721 Change-Id: Idbfebd4f35af629f0f43931b7c5184b334822c7a
* Force inlining on trivial accessors.Ian Rogers2014-04-291-1/+0
| | | | | | | | | Make volatility for GetFieldObject a template parameter. Move some trivial mirror::String routines to a -inl.h. Bug: 14285442 Change-Id: Ie23b11d4f18cb15a62c3bbb42837a8aaf6b68f92
* Fix debugger crash in native method frames.Sebastien Hertz2014-03-171-0/+1
| | | | | | | | | | | | | | | | | | | | | The main crash happens when we try to read (StackFrame::GetValues) or write (StackFrame::SetValues) values in native frames. We use the method's vmap to know where Dalvik registers live but native methods don't have vmap. The fix is to reply with the OPAQUE_FRAME error which indicates local values are not accessible in the frame. We prevent from dereferencing null code item which causes some crashes too. This happens when we compute the line table (Method::LineTable) and variable table (Method::VariableTable) of methods without code: native, proxy and abstract methods. We do not expect to encounter abstract methods though. We take care of these kinds of method when mangling/demangling local value slots. We also fix the location's pc of native and proxy frames where it must be -1 (as 8-byte value). We'll use this property to detect such frames in the JDWP tests. Bug: 13366758 Change-Id: I78e3263fbf2681b5573571c846390d52b9193849
* Add debug code for saving dex file inputsBrian Carlstrom2014-02-201-1/+2
| | | | | | | Also improve some other logging. Bug: 13078746 Change-Id: Ic7a7c201b935e2b117ddc38b652cf39152fe42dc
* Remove blacklistSebastien Hertz2014-02-171-11/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Removes the class initialization blacklist and use transaction to detect and revert class initialization attempting to invoke native method. This only concerns class initialization happening at compilation time when generating an image (like boot.art for the system). In transactional mode, we log every object's field assignment and array update. Therefore we're able to abort a transaction to restore values of fields and array as they were before the transaction starts. We also log changes to the intern string table so we can restore its state prior to transaction start. Since transactional mode only happens at compilation time, we don't need to log all these changes at runtime. In order to reduce the overhead of testing if transactional mode is on/off, we templatize interfaces of mirror::Object and mirror::Array, respectively responsible for setting a field and setting an array element. For various reasons, we skip some specific fields from transaction: - Object's class and array's length must remain unchanged so garbage collector can compute object's size. - Immutable fields only set during class loading: list of fields, method, dex caches, vtables, ... as all classes have been loaded and verified before a transaction occurs. - Object's monitor for performance reason. Before generating the image, we browse the heap to collect objects that need to be written into it. Since the heap may still holds references to unreachable objects due to aborted transactions, we trigger one collection at the end of the class preinitialization phase. Since the transaction is held by the runtime and all compilation threads share the same runtime, we need to ensure only one compilation thread has exclusive access to the runtime. To workaround this issue, we force class initialization phase to run with only one thread. Note this is only done when generating image so application compilation is not impacted. This issue will be addressed in a separate CL. Bug: 9676614 Change-Id: I221910a9183a5ba6c2b99a277f5a5a68bc69b5f9
* Object model changes to support 64bit.Ian Rogers2014-02-061-1/+1
| | | | | | | | | | | | | | | | | | | | | | | Modify mirror objects so that references between them use an ObjectReference value type rather than an Object* so that functionality to compress larger references can be captured in the ObjectRefererence implementation. ObjectReferences are 32bit and all other aspects of object layout remain as they are currently. Expand fields in objects holding pointers so they can hold 64bit pointers. Its expected the size of these will come down by improving where we hold compiler meta-data. Stub out x86_64 architecture specific runtime implementation. Modify OutputStream so that reads and writes are of unsigned quantities. Make the use of portable or quick code more explicit. Templatize AtomicInteger to support more than just int32_t as a type. Add missing, and fix issues relating to, missing annotalysis information on the mutator lock. Refactor and share implementations for array copy between System and uses elsewhere in the runtime. Fix numerous 64bit build issues. Change-Id: I1a5694c251a42c9eff71084dfdd4b51fff716822
* Fix apps with more than one dex file with the same nameBrian Carlstrom2014-02-061-13/+28
| | | | | | | | | | | | Reverts most of 60836d5a9bcf8b30984aae4279a4f6233b0bf622 which I believe was an incorrect attempt to address issue introduced in 8d31bbd3d6536de12bc20e3d29cfe03fe848f9da, which is also reverted here. Also adds some debugging aids include operator<< for DexFile and MemMap and checksum information to OatFile logging. Bug: 12802375 Change-Id: Idd6f7dd487f6e01e9479cd15cd4b61580160e8a3
* Remove unneeded quotingBrian Carlstrom2013-12-101-3/+3
| | | | Change-Id: I87f452e338bd4ff0587e3fc7b0bec3f08a1e7fe6
* Use libziparchive for art zip processing.Narayan Kamath2013-12-091-4/+4
| | | | | | | | | | | This is part of the effort to move all VM & framework zip parsing to a common implementation. This also has the side effect of fixing various TODOs related to crc32 checking. bug: 10193060 Change-Id: I407f9ad5a94fc91d96ff43556adde00a00df1f14
* Faster Signature::operator==(const StringPiece& rhs).Vladimir Marko2013-11-251-0/+26
| | | | | | | Avoid string allocation and resizing, return early if a parameter doesn't match. Change-Id: Ifc929d0c4a7a9d368432f7cae797d4326c6c44be
* Avoid some string allocations.Vladimir Marko2013-11-211-5/+3
| | | | | | Also avoid building a string one character at a time. Change-Id: I3db26226c620a730b95637d5bfc23e2d4715cfb9
* Rewrite intrinsics detection.Vladimir Marko2013-11-181-3/+4
| | | | | | | | | Intrinsic methods should be treated as a special case of inline methods. They should be detected early and used to guide other optimizations. This CL rewrites the intrinsics detection so that it can be moved to any compilation phase. Change-Id: I4424a6a869bd98b9c478953c9e3bcaf1c6de2b33
* Put arguments first in debugger variable table and fix name bug.Jeff Hao2013-11-141-3/+3
| | | | | | Bug: 11569468 Change-Id: I63d45427ded0937c3ab2456fe5cec22da5558e53
* Compacting collector.Mathieu Chartier2013-11-111-4/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The compacting collector is currently similar to semispace. It works by copying objects back and forth between two bump pointer spaces. There are types of objects which are "non-movable" due to current runtime limitations. These are Classes, Methods, and Fields. Bump pointer spaces are a new type of continuous alloc space which have no lock in the allocation code path. When you allocate from these it uses atomic operations to increase an index. Traversing the objects in the bump pointer space relies on Object::SizeOf matching the allocated size exactly. Runtime changes: JNI::GetArrayElements returns copies objects if you attempt to get the backing data of a movable array. For GetArrayElementsCritical, we return direct backing storage for any types of arrays, but temporarily disable the GC until the critical region is completed. Added a new runtime call called VisitObjects, this is used in place of the old pattern which was flushing the allocation stack and walking the bitmaps. Changed image writer to be compaction safe and use object monitor word for forwarding addresses. Added a bunch of added SIRTs to ClassLinker, MethodLinker, etc.. TODO: Enable switching allocators, compacting on background, etc.. Bug: 8981901 Change-Id: I3c886fd322a6eef2b99388d19a765042ec26ab99
* Fix DexFile error handling to close fd properly.Vladimir Marko2013-11-061-33/+34
| | | | Change-Id: I20bf4ec6fdd6e8ced432d12886670537a2952eee
* Remove unused length from DexFile GetString calls.Ian Rogers2013-10-311-4/+2
| | | | | | | Address extra review comments from commit dfb325e0ddd746cd8f7c2e3723b3a573eb7cc111. Change-Id: If76e81e7af5870431901de0bf561e0f827435fe3
* Don't use UTF16 length as length for MUTF8.Ian Rogers2013-10-301-2/+2
| | | | | | Bug 11367555. Change-Id: Ia0b07072a1a49d435c3b71ed9a668b316b7ff5d8
* Throw IOException at source of failing to open a dex file.Ian Rogers2013-10-211-70/+87
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Before is: java.lang.ClassNotFoundException: Didn't find class "GCBench" on path: DexPathList[[zip file "/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar"],nativeLibraryDirectories=[/disk2/dalvik-dev/out/host/linux-x86/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) Suppressed: java.lang.ClassNotFoundException: GCBench at java.lang.Class.classForName(Native Method) at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 1 more Caused by: java.lang.NoClassDefFoundError: Class "LGCBench;" not found ... 5 more And after is: java.lang.ClassNotFoundException: Didn't find class "GCBench" on path: DexPathList[[zip file "/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar"],nativeLibraryDirectories=[/disk2/dalvik-dev/out/host/linux-x86/lib]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) Suppressed: java.io.IOException: Zip archive '/disk2/dalvik-dev/out/host/linux-x86/framework/GCBench.jar' doesn't contain classes.dex at dalvik.system.DexFile.openDexFile(Native Method) at dalvik.system.DexFile.<init>(DexFile.java:80) at dalvik.system.DexFile.<init>(DexFile.java:59) at dalvik.system.DexPathList.loadDexFile(DexPathList.java:268) at dalvik.system.DexPathList.makeDexElements(DexPathList.java:235) at dalvik.system.DexPathList.<init>(DexPathList.java:113) at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48) at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:38) at java.lang.ClassLoader.createSystemClassLoader(ClassLoader.java:128) at java.lang.ClassLoader.access$000(ClassLoader.java:65) at java.lang.ClassLoader$SystemClassLoader.<clinit>(ClassLoader.java:81) at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:137) Suppressed: java.lang.ClassNotFoundException: GCBench at java.lang.Class.classForName(Native Method) at java.lang.BootClassLoader.findClass(ClassLoader.java:781) at java.lang.BootClassLoader.loadClass(ClassLoader.java:841) at java.lang.ClassLoader.loadClass(ClassLoader.java:504) ... 1 more Caused by: java.lang.NoClassDefFoundError: Class "LGCBench;" not found ... 5 more Also, move dex file verifier messages out of logs. In the process the ClassLinker::dex_lock_ needed tidying to cover a smaller scope. Bug 11301553. Change-Id: I80058652e11e7ea63457cc01a0cb48afe1c15543
* am 80f85137: am 7c798419: am 7c3d13ae: Use file magic to determine file ↵Brian Carlstrom2013-10-041-30/+55
|\ | | | | | | | | | | | | type, not file extension. * commit '80f85137828f3ada45de7beb0acd2888ed7b3b24': Use file magic to determine file type, not file extension.
| * Use file magic to determine file type, not file extension.Brian Carlstrom2013-10-031-30/+55
| | | | | | | | | | Bug: 10614658 Change-Id: I9156dfca78ac8cd1c62fb258825cc791629270a4
| * Use class def index from java.lang.Class.Ian Rogers2013-09-211-64/+27
| | | | | | | | | | | | | | | | | | | | | | Bug: 10244719 This removes the computation of the dex file index, when necessary this is computed by searching the dex file. Its only necessary in dalvik.system.DexFile.defineClassNative and DexFile::FindInClassPath, the latter not showing up significantly in profiling with this change. (cherry-picked from 8b2c0b9abc3f520495f4387ea040132ba85cae69) Change-Id: I20c73a3b17d86286428ab0fd21bc13f51f36c85c
* | Introduce Signature type to avoid string comparisons.Ian Rogers2013-09-261-29/+37
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Method resolution currently creates strings to then compare with strings formed from methods in other dex files. The temporary strings are purely created for the sake of comparisons. This change creates a new Signature type that represents a method signature but not as a string. This type supports comparisons and so can be used when searching for methods in resolution. With this change malloc is no longer the hottest method during dex2oat (now its memset) and allocations during verification have been reduced. The verifier is commonly what is populating the dex cache for methods and fields not declared in the dex file itself. Change-Id: I5ef0542823fbcae868aaa4a2457e8da7df0e9dae
* | Move hot utf routines into -inl.h.Ian Rogers2013-09-231-1/+1
| | | | | | | | Change-Id: I7050d8282a7e5870b2bf671d6867c57625e00ccc
* | Use class def index from java.lang.Class.Ian Rogers2013-09-191-64/+27
|/ | | | | | | | | | | | Bug: 10244719 Depends on: https://googleplex-android-review.git.corp.google.com/362363 This removes the computation of the dex file index, when necessary this is computed by searching the dex file. Its only necessary in dalvik.system.DexFile.defineClassNative and DexFile::FindInClassPath, the latter not showing up significantly in profiling with this change. Change-Id: I20c73a3b17d86286428ab0fd21bc13f51f36c85c
* Revert "Remove bogus fastpath from String::Equals(const StringPiece&)"Brian Carlstrom2013-09-061-14/+0
| | | | | | | This reverts commit 8438ed31e10f3881ed92f03877d5edaca7d5b48c. Bug: 10614658 Change-Id: I335f10a7140e1644957bc1cee21a9b310a558499
* Remove bogus fastpath from String::Equals(const StringPiece&)Brian Carlstrom2013-09-061-0/+14
| | | | | Bug: 10614658 Change-Id: I907ec77a65c1ae29e800356abdf755a457620081
* Make DexFiles opened from files readonly by default, but writable during dex2oatBrian Carlstrom2013-08-291-12/+16
| | | | | Bug: 9618388 Change-Id: I83f2e16ee8446a79a94a84971146d807bb0c9ee0
* Refactor java.lang.reflect implementationBrian Carlstrom2013-08-131-5/+4
| | | | | | | | | | | Cherry-picked from commit ed41d5c44299ec5d44b8514f6e17f802f48094d1. Move to ArtMethod/Field instead of AbstractMethod/Field and have java.lang.reflect APIs delegate to ArtMethod/ArtField. Bug: 10014286. Change-Id: Iafc1d8c5b62562c9af8fb9fd8c5e1d61270536e7
* Make verifier allow integral types to be put in integral type arrays.Jeff Hao2013-08-011-1/+0
| | | | | | | | | | | This fixes a problem where the verifier was rejecting when an integer is put into a byte array. This also more closely matches the RI. Also fixes various issues with debugging checks caught by cts. Bug 10097083 Change-Id: Ie816fcdd85d6dc898feffa1e3fea8cfc2c6946ff
* Fix cpplint whitespace/comments issuesBrian Carlstrom2013-07-261-1/+1
| | | | Change-Id: Iae286862c85fb8fd8901eae1204cd6d271d69496