the first time a surface was connected, the values returned
by query NATIVE_WINDOW_DEFAULT_{WIDTH|HEIGHT} and
NATIVE_WINDOW_TRANSFORM_HINT were wrong until a call
to queueBuffer was performed.
Bug: 5137366, 5121607
Change-Id: I7ac6b5b0daa876638f6bed7c20f286a6e6d984f6
the original connect/disconnect hooks are deprecated
and replace by api_connect/api_disconnect. the original
hooks are no no-ops.
api_connect/api_disconnect is now only called from the
android framework.
Bug: 5057915
Change-Id: I8ca64cd1acd6cabf915bf54689ec2e5f6dfa495a
Bug: 5064702
Introduced the concept of an InputListener to further decouple
the InputReader from the InputDispatcher. The InputListener
exposes just the minimum interface that the InputReader needs
to communicate with the outside world. The InputReader
passes arguments to the InputListener by reference, which makes
it easy to queue them up.
Consolidated all of the InputReader locks into one simple global
Mutex. The reason this wasn't done before was due to potential
re-entrance in outbound calls to the InputDispatcher. To fix this,
the InputReader now queues up all of the events it wants to send
using a QueuedInputListener, then flushes them outside of the
critical section after all of the event processing is finished.
Removing all of the InputMapper locks greatly simplifies the
implementation.
Added tests for new stylus features such as buttons, tool types,
and hovering.
Added some helpers to BitSet32 to handle common code patterns
like finding the first marked bit and clearing it.
Fixed a bug in VelocityTracker where the wrong pointer trace
could get cleared when handling ACTION_POINTER_DOWN. Oops.
Changed PointerCoords so it no longer stores useless zero
axis values. Removed editAxisValue because it is not very
useful when all zero value axes are absent and therefore
cannot be edited in place.
Added dispatch of stylus hover events.
Added support for distance and tool types.
Change-Id: I4cf14d134fcb1db7d10be5f2af7b37deef8f8468
This change relaxes an error check in SurfaceTexture::setBufferCount to
allow clients to explicitly set a buffer count of 2. The clients that
will do this are camera and video decode. Previously it was thought
that for those clients we would always use async mode, which requires a
minimum of 3 buffers. However, we now believe that for some devices it
may make sense to use synchronous mode (with 2 buffers) to reduce memory
usage.
Bug: 5088418
Change-Id: I620a0ef75075745be9d6c8219e0246aaf33ba950
GraphicAllocator debugging cannot deal with
custom HAL formats. make this more obvious in the
log.
Change-Id: I202e58a7f213f32e725aa4eac62cdf6e50ca5894
We should use all-makefiles-under instead.
all-subdir-makefiles can be used only before any "include" statement.
Before this change, both subdirs were actually not included.
Change-Id: I6bf35d07f294a5012c9322096f999ac26e37432f
The built-in ZipFile class was quite a long time to find an unpack
libraries. Move everything to using the libutils ZipFileRO class that
goes quite a bit faster. Initial measurements are 6 times faster than
the Java code.
Also, read files off the disk and compare their CRC against the APK's
CRC to see if we need to write the new file to disk. This also cuts down
the bootup time by up to a second per APK that has native files.
Change-Id: Ic464a7969a17368fb6a6b81d026888c4136c7603
The Surface is already using SurfaceTexture internally and it is parcelable. This
is intended to replace and phase out ParcelSurfaceTexture in favor of creating a
new Surface.java object from an existing SurfaceTexture.
Change-Id: I8e2dd86614523da6abed6403e1d705a68fa19fdf
This change removes support for conditionally using the GL_TEXTURE_2D
target for SurfaceTexture textures with RGB buffers. It also enables
and fixes the RGB-based SurfaceTexture tests.
Change-Id: I9a251a981cf66af6b048b2e4c3fe7231e4774f4d
This change adds the 'abandon' method to the SurfaceTexture C++ class.
This method may be used to put the SurfaceTexture in an abandoned state,
causing all ISurfaceTexture methods to fail.
Change-Id: Ibd261f7b73f44e2bec36a8508bf92113cfb7cf95
This change adds a test to ensure that a GL driver that's blocking on a
call to dequeueBuffer does not block other GL threads from rendering and
queueing buffers.
Change-Id: Ifdd234effc534b6a9cf8522ca87f64da5bb0bbd6
- fixed uninitialized variable
- set hint to indentity when transform is too complex
- make sure FrameBufferNativeWindow doesn't fail on needed perform commands
Bug: 4487161
Change-Id: I7cb2b0869b72404732eca7cb2d145ff669e2ed9b
This change removes the SurfaceTexture::getAllocator method, as it's no
longer needed. Proper refcounting of the Gralloc buffers is now handled
by the IGraphicBufferAlloc binder marshalling code.
Change-Id: I5cffa6ebfc1bc5828fb7ce0e0a5b2f55cd8479da
This makes ANativeWindow_lock/ANativeWindow_unlockAndPost work
with ANativeWindows implemented by Surface and SurfaceTextureClient.
Also, Surface now inherits directly from SurfaceTextureClient.
Bug: 5003724
Change-Id: I9f285877c7bae9a262e9a7af91c2bae78804b2ef
This change makes the ANativeWindow connect and disconnect calls result
in an IPC to the SurfaceTexture object. This will allow us to prevent
multiple simultaneous connections from different processes.
Change-Id: Id9aa1003b1335b96ca6bd4a1f5a67aa433d42efb
This change fixes a couple different issues in the
SurfaceTextureGLToGLTest test fixture:
- incorrect use of conditions
- move logging after the locks are acquired
- call the parent class's TearDown method
- clean up the SurfaceTexture before eglTerminate gets called
Change-Id: I6960e5ab7f144225f01a2089d3f849c99fed0b38
This change adds support to SurfaceTextureClient for the new enum values
that can be passed to the ANativeWindow connect call.
Change-Id: I8c15418909e43a15673a9b22a5eb40df6923b273
Fixed a potential bug where calling replaceAt with a reference to
an existing element in the vector at the same index would cause
the element to be destroyed while being copied to itself.
Refactored the conditions in _grow and _shrink for clarity.
The computations are exactly the same but I think it reads better
this way. In particular, the ssize_t variable 's' is gone: it didn't
need to be signed anyways because its value could never be negative.
Change-Id: If087841c15e6a87160eee874720c4a77eb0e99a6
On review of the code, _grow and _shrink are checking for conditions
that cannot happen and that don't even really make sense. For
example, if _shrink is called with where + amount > mCount then
this is really bad, however the check only considered the case
when where >= mCount and then it would arbitrarily choose a new
value for where. Huh?
As it happens, the callers are correctly validating the
arguments before passing them down to these methods so we can
get rid of this code.
Change-Id: I921852dba8997065bb0e9cac733e82028d14afcd
Zlib compression, with a full flush between each application's
data. Encryption will be performed on the already-compressed data
once that's implemented.
On restore, the streamed data is similarly uncompressed on the fly.
Change-Id: I19b65c88e759a66527d10913d18fffa9df0bc011
This change fixes how the Android EGL layer overrides the size and
format of an ANativeWindow in eglCreateWindowSurface. The new behavior
is to leave the size untouched when overriding the format. The previous
behavior was to reset the ANativeWindow to use the default size set by
the ANativeWindow implementation.
It also adds two new 'perform' methods to the ANativeWindow interface:
set_buffers_dimensions and set_buffers_format, and redefines the
behavior of set_buffers_geometry to be the combination of these two new
methods.
Additionally, this change adds an error check for the return value of
the new native_window_set_buffers_format call, which required adding a
(stub) handler for to FramebufferNativeWindow.
Change-Id: I805c7ccd8d4730dfb132d10d8bc3fb058a0b9df1
- renderscript now calls EGL directly instead of relying on this function
- surfaceflinger also does its own EGLConfig selection
- selectConfigForPixelFormat stays for legacy reason (many tests use it) but
it now only tries to match the alpha channel of the format rather than the
format itself.
this will allow implementations who don't support the exact formats
defined in the HAL to work properly.
Bug: 4998223
Change-Id: Ic664dfc14d5072a514b6f77a115d1521bfc1578f
This API is intended for applications that need to read a thread's
scheduling group, while using the higher-level (C++) family of thread APIs.
Change-Id: I5e58017f74c3989b20b5b1cc2bc4483c95720520
This change enables the following four SurfaceTextures tests:
UpdateTexImageBeforeFrameFinishedWorks
UpdateTexImageAfterFrameFinishedWorks
RepeatedUpdateTexImageBeforeFrameFinishedWorks
RepeatedUpdateTexImageAfterFrameFinishedWorks
Change-Id: I7632630bc97873e50d4a765ffc44a86f16ae62f1
- put the test window at the front most screen position
- use RGBA_8888 which is a mandatory format
- handle devices that don't support the protected usage flags
Bug: 4950464
Change-Id: I0005fb667cfe094e5978816e2924b294c5ef817e
Fixed some issues where inconsistent streams of events could
be generated by the dispatcher, particularly when switching from
hovering with one device to hovering with another.
Fixed a bug where the touch pad would fail to generate a new
HOVER_MOVE following a tap event. As a result, the hover event
stream would not resume until the user touched the touch pad
again.
Change-Id: I444dce84641fb12e56a0af84c931520771d6c493
This change adds a test to verify that proper synchronization is done
when using SurfaceTexture to use CPU generated images as OpenGL ES
textures in 'synchronous mode'. Synchronous mode is particularly tricky
because SurfaceTexture will allow the buffer that's currently bound to
the GL texture to be dequeued. We rely on Gralloc's lock function to
block until this buffer is no longer being used by the OpenGL ES.
Change-Id: I1c4e37f3e9d60ab9a0905a90a1f5060fda8e485c
This is intended to absorb the cost of the IPC
to the permission controller.
Cached permission checks cost about 3us, while
full blown ones are two orders of magnitude slower.
CAVEAT: PermissionCache can only handle system
permissions safely for now, because the cache is
not purged upon global permission changes.
Change-Id: I8b8a5e71e191e3c01e8f792f253c379190eee62e
This change moves the point at which queued buffers get consumed to
after any error checks that could cause updateTexImage to fail. This
way, if updateTexImage returns an error the buffer remains queued.
This change alters the conditions under which the onFrameAvailable
callback gets called by the C++ SurfaceTexture class. The new behavior
is to call the callback whenever a frame gets queued that will be
visible to the buffer consumer. This means that buffers queued in
synchronous mode always trigger the callback, as those buffers will
remain pending until they are consumed. Buffers queued in asynchronous
mode will only trigger the callback if there was not previously an
unconsumed buffer pending.
The new behavior means that a consumer should perform a draw operation
exactly once for every onFrameAvailable call that it recieves. This
change also modifies SurfaceFlinger and the SurfaceTexture JNI to
support of the new behavior.
Change-Id: I8b2c6e00961d3d58b11c6af50b555b6e4c5f5b40
The offset that is used in the creation of the MemoryHeapBase must be saved, so
that it can be used to recreate the Heap when an IMemory object is passed
across process boundary through the binder.
Change-Id: Ie618fb5c0718e6711f55ed9235616fd801e648dc
Signed-off-by: Anu Sundararajan <sanuradha@ti.com>
Signed-off-by: Iliyan Malchev <malchev@google.com>
This new API will be used by applications that previously used the
lower-level pthread APIs (including pthread_join). Centralizing on the
Thread class instead of pthread will permit additional functionality to
be added later in only one location.
Change-Id: I8460169ac9c61ac9f85752405ed54c94651058d7
This change makes the SurfaceTexture GL tests use a large (512x512)
framebuffer. The tests now use glViewport to render to a region of the
framebuffer with a size matching that of the texture being drawn. The
Npot test pixel checks must be changed because now the rendered region
is the same size as the texture.
Change-Id: Icc41803189c25e33ba1da7d2470720f0a11f3e4b
This change adds a NULL check when searching the slot list in
SurfaceTextureClient for the slot corresponding to a buffer being
queued or canceled.
Bug: 4645023
Change-Id: I806cbc1e34da118ea33a83c4f25ce8193ba1c3ad
The version of MinGW we use doesn't have nrand48() which is really lame,
but we need to use libutils in the Windows SDK.
Change-Id: If854c03dbf02bc29e79f49e4539f08c2bf057517
This change increases the Surface layer used for displaying the test
results so that the tests will be visible over other windows in the
system.
Change-Id: I47f147f8743ff2a39d57d551811668371202bd31
Add the concept of synchronous dequeueBuffer in SurfaceTexture
Implement {Surface|SurfaceTextureClient}::setSwapInterval()
Add SurfaceTexture logging
fix onFrameAvailable
This change adds a test to verify that querying the format of a
SurfaceTextureClient immediately after setting it returns the correct
result. The test is currently disabled because it does not pass.
Change-Id: I5bddb39c5bf96d6104624094383d410ed913e9f3
This change disables the UpdateTexImageAfterFrameFinishedWorks test
because it's currently causing deadlocks on some devices.
Change-Id: Ic9186db207e8d656f3af5d86fa138c7d96393c55
This change adds a default tolerance of 2 to all the pixel value checks
in the SurfaceTexture tests.
Change-Id: Id5a7cdffdfae16076e2daf4964a3326105b5ae2c
This change adds some tests to verify streaming images from one GL
thread to another via SurfaceTexture. Currently the tests do not
validate the correctness of the streamed images, but rather simply
verify that this streaming does not cause a deadlock. 3 of the 4 tests
are currently disabled because they do cause deadlocks on some devices.
Change-Id: I5677942053190063b97f370dba96c116711bc3bb
This change adds a test verifying that with no transform set on the
SurfaceTextureClient, the SurfaceTexture will return an identity
transform matrix. It also verifies this same effect in the presence of
an additional call to native_window_set_buffer_count just before the
call to getTransformMatrix.
Bug: 4490420
Change-Id: Ic5adfa29b5696cc2b451433834e3758ef20c5edd
This change moves the computation of the transform matrix out of
getTransformMatrix and instead performs the computation when
updateTexImage gets called. This is needed in order for
getTransformMatrix to succeed even if the buffers have been freed (e.g.
by changing the buffer count) because the computation depends upon the
properties of the current GraphicBuffer.
Change-Id: Ied541ab8747b7ad604f862717135f9a16a816be9
Bug: 4490420
pthread_create already includes the necessary memory barriers:
- parent at pthread_create : pthread_mutex_unlock(start_mutex)
- child at __thread_entry : pthread_mutex_lock(start_mutex)
Add lock around uses of mThread.
Added comments:
- uses of mThread require lock
- androidCreateRawThreadEtc returned ID is not safe for direct use from non-parent threads.
Change-Id: I18cb296b41ddaf64cf127b57aab31154319b5970
Don't emit tar blocks for directories with an invalid nonzero size. Also, if
such an entry is encountered during restore, don't actually attempt to treat
it as valid and thus skip over the next actual tar entry.
This patch also adds tracking of the data actually consumed during restore,
and reports a total at the end of stream.
Change-Id: I625173f76df3c007e899209101ff2b587841f184
...for Market App iRunner
There were a lot of serious issues with how we updated (or often didn't update)
the display and resource state when switching compatibility mode in conjunction
with restarting and updating application components. This addresses everything
I could find.
Unfortunately it does *not* fix this particular app. I am starting to think this
is just an issue in the app. This change does fix a number of other problems
I could repro, such as switching the compatibility mode of an IME.
Also a few changes here and there to get rid of $#*&^!! debug logs.
Change-Id: Ib15572eac9ec93b4b9966ddcbbc830ce9dec1317
this bug was introduced recently. it caused RefBase's weakref_impl
structure to be leaked for every RefBase object (about 20 bytes).
Change-Id: Id85e749ba04521199555dd701198edd097c313d4
this bug was introduced recently. it caused RefBase's weakref_impl
structure to be leaked for every RefBase object (about 20 bytes).
Change-Id: Ia9b155fbfa643ef72cfb8129e96260a3b806a78c
Every available shared-storage volume is backed up, tagged with its
ordinal in the set of mounted shared volumes. This is an approximation
of "internal + the external card". This lets us restore things to the
same volume [or "equivalent" volume, in the case of a cross-model
restore] as they originated on.
Also fixed a bug in the handling of files/dirs with spaces in
their names.
Change-Id: I380019da8d0bb5b3699bd7c11eeff621a88e78c3
Bug: 4364920
Velocity damping proved to be a bad idea because it would
cause a significant ramp in velocity at the beginning of
a gesture, instead of the desired smooth behavior. Oh well.
Change-Id: Ie631946f47ef2492bd71fbed1ab44bbb39a875a8
Fix a race that could cause GL commands to be executed from the wrong thread.
RefBase subclasses can now decide how they want to be destroyed.
Fix a race in SurfaceFlinger that could cause layers to be leaked forever.
Fix a race-condtion in SurfaceFlinger that could lead to a crash.
initial cherry-pick:
resolved conflicts for merge of b9783b49 to honeycomb-plus-aosp
Change-Id: I2a335e03fff219e35c18a7b0089b3a11d636576f
Usage: adb restore [tarfilename]
Restores app data [and installs the apps if necessary from the backup
file] captured in a previous invocation of 'adb backup'. The user
must explicitly acknowledge the action on-device before it is allowed
to proceed; this prevents any "invisible" pushes of content from the
host to the device.
Known issues:
* The settings databases and wallpaper are saved/restored, but lots
of other system state is not yet captured in the full backup. This
means that for practical purposes this is usable for 3rd party
apps at present but not for full-system cloning/imaging.
Change-Id: I0c748b645845e7c9178e30bf142857861a64efd3
Add support for 9-axis gravity and linear-acceleration sensors
virtual orientation sensor using 9-axis fusion
Change-Id: I6717539373fce781c10e97b6fa59f68a831a592f
Added a new PointerIcon API (hidden for now) for loading
pointer icons.
Fixed a starvation problem in the native Looper's sendMessage
implementation which caused new messages to be posted ahead
of old messages sent with sendMessageDelayed.
Redesigned the touch pad gestures to be defined in terms of
more fluid finger / spot movements. The objective is to reinforce
the natural mapping between fingers and spots which means there
must not be any discontinuities in spot motion relative to
the fingers.
Removed the SpotController stub and folded its responsibilities
into PointerController.
Change-Id: Ib647dbd7a57a7f30dd9c6e2c260df51d7bbdd18e
Some drivers report individual finger updates one at a time
instead of all at once. When 10 fingers are down, this can
cause the framework to have to handle 10 times as many events
each with 10 times as much data. Applications like
PointerLocation would get significantly bogged down by all
of the redundant samples.
This change coalesces samples that are closely spaced in time,
before they are dispatched, as part of the motion event batching
protocol.
Increased the size of the InputChannel shared memory buffer so
that applications can catch up faster if they accumulate a
backlog of samples.
Change-Id: Ibc6abf8af027d9003011ac75caa12941080caba3
The SurfaceTextureSyncModeWaitRetire test was disabled. It is failing
because of the synchronization hacks that were added to SurfaceTexture
to work around bugs in vendor device drivers.
Change-Id: I09a74538bfe14a04833acb6847471e00826cc7fc
This change fixes the MIN_UNDEQUEUED_BUFFERS error check in
dequeueBuffer. The check should only be performed if a buffer has been
queued since the last time the buffer count was changed by the client.
The check must be applied conditionally because video decoders require
all the bufferes to be dequeued and registered before beginning the
decode.
Change-Id: I08d96b380544e395c2fcf0f3983a199bfd695b09
This change fixes up some stale comments, member variable names, log
messages and disables a failing test.
Change-Id: Ic1d3344b18066cf710e4a42838b2417c6b1f2f6c
* commit 'c9cd2387b6938a6fbefc731d2177902266f2a130':
Fix a race that could cause GL commands to be executed from the wrong thread.
RefBase subclasses can now decide how they want to be destroyed.
Fix a race in SurfaceFlinger that could cause layers to be leaked forever.
Fix a race-condtion in SurfaceFlinger that could lead to a crash.
Added a timeout mechanism to EventHub and InputReader so that
InputMappers can request timeouts to perform delayed processing of
input when needed.
Change-Id: I89c1171c9326c6e413042e3ee13aa9f7f1fc0454
Replaced VelocityTracker with a faster and more accurate
native implementation. This avoids the duplicate maintenance
overhead of having two implementations.
The new algorithm requires that the sample duration be at least
10ms in order to contribute to the velocity calculation. This
ensures that the velocity is not severely overestimated when
samples arrive in bursts.
The new algorithm computes the exponentially weighted moving
average using weights based on the relative duration of successive
sample periods.
The new algorithm is also more careful about how it handles
individual pointers going down or up and their effects on the
collected movement traces. The intent is to preserve the last
known velocity of pointers as they go up while also ensuring
that other motion samples do not count twice in that case.
Bug: 4086785
Change-Id: I95054102397c4b6a9076dc6a0fc841b4beec7920
1. Single finger tap performs a click.
2. Single finger movement moves the pointer (hovers).
3. Button press plus movement performs click or drag.
While dragging, the pointer follows the finger that is moving
fastest. This is important if there are additional fingers
down on the touch pad for the purpose of applying force
to an integrated button underneath.
4. Two fingers near each other moving in the same direction
are coalesced as a swipe gesture under the pointer.
5. Two or more fingers moving in arbitrary directions are
transformed into touches in the vicinity of the pointer.
This makes scale/zoom and rotate gestures possible.
Added a native VelocityTracker implementation to enable intelligent
switching of the active pointer during drags.
Change-Id: I7b7ddacc724fb1306e1590dbaebb740d3130d7cd
This adds a destroy() virtual on RefBase which
sublasses can implement. destroy() is called
in lieu of the destructor whenthe last strong
ref goes away.
Bug: 4483050
Change-Id: I8cbf6044a6fd3f01043a45592b5a60fa1e5fade2
This adds a destroy() virtual on RefBase which
sublasses can implement. destroy() is called
in lieu of the destructor whenthe last strong
ref goes away.
In resources.arsc files, a resource is represented by a specification
block and one or more value blocks. In rare cases, a resource name
is also given a new resource ID, a specification block and no values
blocks. This commit ensures idmap generation does not fail if such an
entry is encountered.
Change-Id: I32302a0b07a7a320b7eeb31886931be3bb7b7e9a
This change adds an implementation of a cache that stores key/value
pairs of unstructured binary blobs.
Change-Id: Idd01fdabedfa3aed6d359a6efb0592967af52651
* provide placeholder UI showing backup/restore start/stop/timeout
* don't kill the progress UI in mid stream
* tidy up the pax extended header data writing a little
Change-Id: Ife0cb78e3facb541d8327f1d5ca5fe77faa6cbca
Added the concept of pointer properties in a MotionEvent.
This is currently used to track the pointer tool type to enable
applications to distinguish finger touches from a stylus.
Button states are also reported to application as part of touch events.
There are no new actions for detecting changes in button states.
The application should instead query the button state from the
MotionEvent and take appropriate action as needed.
A good time to check the button state is on ACTION_DOWN.
As a side-effect, applications that do not support multiple buttons
will treat primary, secondary and tertiary buttons identically
for all touch events.
The back button on the mouse is mapped to KEYCODE_BACK
and the forward button is mapped to KEYCODE_FORWARD.
Added basic plumbing for the secondary mouse button to invoke
the context menu, particularly in lists.
Added clamp and split methods on MotionEvent to take care of
common filtering operations so we don't have them scattered
in multiple places across the framework.
Bug: 4260011
Change-Id: Ie992b4d4e00c8f2e76b961da0a902145b27f6d83
You can now specify resource configuration variants "wNNNdp"
and "hNNNdp". These are the minimum screen width/height in "dp"
units. This allows you to do things like have your app adjust
its layout based only on the about of horizontal space available.
This introduces a new configuration change flag for screen size.
Note that this configuration change happens each time the orientation
changes. Applications often say they handle the orientation change
to avoid being restarted at a screen rotation, and this will now
cause them to be restarted. To address this, we assume the app can
handle this new config change if its target SDK version is < ICS.
Change-Id: I4acb73d82677b74092c1da9e4046a4951921f9f4
'tar' supports only 100-character paths; 'ustar' supports only
155+100 character prefix + paths; neither supports files larger
than about 8 gigabytes. We now use the POSIX.1-2001 'pax'
extended tar format for those files in the backup stream that
are too large or have too-long paths for the 'ustar' format.
Change-Id: I2f256823091deaec9b1ccea685d2344753c6cb67
This change the binder protocol between SurfaceTextureClient
and SurfaceTexture. dequeueBuffer() now takes the requested
parameters for the buffer. SurfaceTexture decides if the
buffer needs to be reallocated and does the allocation
if needed. In that case it returns BUFFER_NEEDS_REALLOCATION
to tell SurfaceTextureClient that it needs to call
requestBuffer (which all parameters have been removed) to
acquire a pointer to the buffer.
dequeueBuffer and requestBuffer could be folded into a single
IPC call, but we chose to optimize the case where buffers are
not created and avoid some complexity in the marshalling code.
Change-Id: I097a7f6f40a3491e10f3f3742eab33999286c304