Commit graph

55 commits

Author SHA1 Message Date
Tom Cherry
6fd8d3bb1b init: Allow matching empty property values
When we have a property match along with an event trigger, we
currently don't allow matching empty property values, in other words,
properties that are unset.  For example, the below trigger would never
be run:

on zygote-start && property:persist.sys.fuse=""

That doesn't make sense though, it should be possible to match an
empty property value, so this change allows that trigger to match when
persist.sys.fuse is either empty or not set.

This continues to not match a '*' to an empty property, so

on zygote-start && property:persist.sys.fuse=*

will not run if persist.sys.fuse is empty or unset.

Test: the above triggers run appropriately
Change-Id: Ia57de7b96ad352590d0c82ff4ae95060b7361976
2019-08-12 09:31:42 -07:00
Tom Cherry
e269a721dc Merge "init: ignore ENOENT from fewer builtins" 2019-08-06 15:19:48 +00:00
Tom Cherry
4772f1da47 init: check the arguments of builtins during the build
Host init verifier already checks that the names and number of
arguments for builtins are correct, but it can check more.  This
change ensures that property expansions are well formed, and that
arguments that can be parsed on the host are correct.  For example it
checks that UIDs and GIDs exist, that numerical values can be parsed,
and that rlimit strings are correct.

Test: build

Change-Id: Ied8882498a88a9f8324db6b8d1020aeeccc8177b
2019-08-01 10:54:47 -07:00
Tom Cherry
c5cf85db23 init: don't log in expand_props directly
It's better to pass the error message to the caller to determine how
best to print the error.

Test: build
Change-Id: Id8857c459df2f26c031650166609608d20e4d051
2019-08-01 10:34:58 -07:00
Tom Cherry
d17c37952d init: ignore ENOENT from fewer builtins
Previously we were ignoring ENOENT from all builtins as
rootdir/init.rc has many legacy commands that we need to keep for
backwards compatibility, but are otherwise no longer relevant.

However, this wasn't catching actual issues, for example chown failing
due to not finding the user or group name.  This change therefore
reduces the scope of ignoring ENOENT to the only the extraneous errors
in builtins.

Test: boot CF and walleye without seeing errors from init.rc
Test: see errors from invalid users/groups in chown
Change-Id: Ia8e14fa2591e083cb1736c313a3e55515bc5d15e
2019-07-30 12:44:35 -07:00
Tom Cherry
d52a5b3c10 init: simplify keyword_map
I've heard that keyword_map is too complex, in particular the tuple
and the pair in BuiltinFunctionMap, so this change removes a lot of
that complexity and, more importantly, better documents how all of
this works.

Test: boot, init unit tests

Change-Id: I74e5f9de7f2ec524cb6127bb9da2956b5f307f56
2019-07-23 14:39:38 -07:00
Tom Cherry
7c1d87e490 init: fix clang-tidy performance issues
Test: boot, init unit tests
Change-Id: Iccf34d2fedfa543dd9f29e010cbb6d8fe9cf5983
2019-07-10 12:59:02 -07:00
Tom Cherry
bbcbc2ffb3 init: replace Result<Success> with Result<void>
Now that Result<T> is actually expected<T, ...>, and the expected
proposal states expected<void, ...> as the way to indicate an expected
object that returns either successfully with no object or an error,
let's move init's Result<Success> to the preferred Result<void>.

Bug: 132145659
Test: boot, init unit tests
Change-Id: Ib2f98396d8e6e274f95a496fcdfd8341f77585ee
2019-06-10 12:39:18 -07:00
Jiyong Park
8fd64c8af1 Move result.h from init to libbase
The Result, Error, ErrnoError are quite generic. Moving them from init
to libbase so that they can be used from other places.

Bug: 132145659
Test: libbase_test
Change-Id: Id774a587f74380fadd7a0fc88c0aa892c3d9a489
2019-06-06 08:58:55 +09:00
Tom Cherry
9949ec5f56 init: replace Result<> with expected<>
Android-base has an implementation of the future std::expected<>.
This provides the same baseline functionality as Result<>, so use it
instead of our own version.

Bug: 132145659
Test: boot, init unit tests
Change-Id: I11e61bcb5719b262a6420483ed51a762826a9e23
2019-05-22 15:23:01 -07:00
Tom Cherry
018a438ff0 init: use rvalues references for callees of ParseLineSection()
ParseLineSection() provides 'args' as an rvalue reference, so its
callers can and should use it as such.  This saves some copying
overhead and cleans up the code a bit.

Test: boot
Change-Id: Ib906318583dc81de9ea585f5f09fdff35403be1b
2018-10-17 11:30:53 -07:00
Elliott Hughes
dc80312628 libbase: add host properties support.
Move init and libprocessgroup away from their existing hacks.

Bug: N/A
Test: ran tests
Change-Id: Ifabdd38e0cc4ab2582f1ea59d32159d386f48eb6
2018-05-24 18:04:31 -07:00
Tom Cherry
de6bd50d42 init: add host side parser for init
Create a host side parser for init such that init rc files can be
verified for syntax correctness before being used on the device.

Bug: 36970783
Test: run the parser on init files on host

Change-Id: I7e8772e278ebaff727057308596ebacf28b6fdda
2018-02-28 10:45:45 -08:00
Tom Cherry
9cbf57048c Move all Action parsing into ActionParser
Bug: 36970783
Test: Build
Change-Id: Iea2d97fb45c3e88bc83fb72d6fa67049be42cfa9
2018-02-14 16:37:17 -08:00
Tom Cherry
7fd3bc27ec Move ActionManager to its own file
Bug: 36970783
Test: build
Change-Id: I08fa39052236b462249f79de1d02bf02bdbf4c84
2018-02-14 16:37:09 -08:00
Tom Cherry
0f6417f232 Move ActionParser to its own file
Bug: 36970783
Test: build
Change-Id: Idd5b923e4789760bb9ef67c10982b2642bc6a31a
2018-02-13 15:26:14 -08:00
Jaekyun Seok
eeb2188554 Apply the whitelist of actionable system properties
This whitelist will be applied only when
ro.actionable_compatible_property.enabled is true.

Bug: 38146102
Test: tested on walleye with ro.actionable_compatible_property.enabled=true
Change-Id: Ifd7211396b53e50a06d79e7c67224e2b38ef7c9d
2018-01-18 04:38:01 +09:00
Tom Cherry
c49719fc5d init: always expand args in subcontext
Currently init expands properties in arguments only when those
commands are run in a subcontext.  This creates a hole where
properties that should not be accessible from a given subcontext of
init can be accessed when running a command in the main init
executable (for example `start`).

This change creates a callback in subcontext init that simply expands
and returns arguments back to the main init process, to ensure that
only those properties that a subcontext can access get expanded.

Bug: 62875318
Test: boot bullhead, new unit tests
Change-Id: I2850009e70da877c08e4cc83350c727b0ea98796
2018-01-12 10:35:26 -08:00
Elliott Hughes
579e682628 Add std::string StartsWith*/EndsWith* overloads.
We should have done this from the beginning. Thanks to Windows, we're not
going to be able to switch libbase over to std::string_view any time soon.

Bug: N/A
Test: ran tests
Change-Id: Iff2f56986e39de53f3ac484415378af17dacf26b
2017-12-20 09:42:22 -08:00
Steven Moreland
7d0a5c3656 EndSection returns Result<Success>
Allow it to fail. When there is an error for a section ending,
print the error pointing to the line where the section starts.

Bug: 69050941
Test: boot, init_tests
Change-Id: I1d8ed25f4b74cc9ac24d38b8075751c7d606aea8
2017-11-15 10:39:29 -08:00
Tom Cherry
cb0f9bbc85 init: run vendor commands in a separate SELinux context
One of the major aspects of treble is the compartmentalization of system
and vendor components, however init leaves a huge gap here, as vendor
init scripts run in the same context as system init scripts and thus can
access and modify the same properties, files, etc as the system can.

This change is meant to close that gap.  It forks a separate 'subcontext'
init that runs in a different SELinux context with permissions that match
what vendors should have access to.  Commands get sent over a socket to
this 'subcontext' init that then runs them in this SELinux context and
returns the result.

Note that not all commands run in the subcontext; some commands such as
those dealing with services only make sense in the context of the main
init process.

Bug: 62875318
Test: init unit tests, boot bullhead, boot sailfish

Change-Id: Idf4a4ebf98842d27b8627f901f961ab9eb412aee
2017-09-29 13:06:26 -07:00
Tom Cherry
68f2a46145 init: enable error reporting of builtin functions
Enable error reporting when builtin functions fail.  These errors are
now reported with full context including the source file and line
number, e.g.

init: Command 'write /sys/module/subsystem_restart/parameters/enable_debug ${persist.sys.ssr.enable_debug}' action=early-boot (/init.bullhead.rc:84) took 0ms and failed: cannot expand '${persist.sys.ssr.enable_debug}'

There are two small caveats:
1) There are nearly 200 reports of builtins failure due to "No such
   file or directory".  Many of these are due to legacy paths included
   in rootdir/init.rc.  Until they are cleaned up, reporting of these
   failures is disabled.
2) Similarly, symlink is often used to create backwards compatible
   symlinks.  By their very nature, these calls are expected to fail
   on newer systems that do already use the new path.  Due to this,
   failures of symlink due to EEXIST are not reported.

Bug: 38038887
Test: boot bullhead, only see true errors reported from builtins.
Change-Id: I316c13e3adc992cacc6d79ffee987adc8738fca0
2017-08-23 11:05:37 -07:00
Tom Cherry
130e3d7204 init: pass errors from one Result<T> to another better
Result<T> currently has two problems,
1) A failing Result<T> cannot be easily constructed from a Result<U>'s
error.
2) errno is lost when passing .error() through multiple Result<T>'s

This change fixes both problems having Result<T>::error() return a
ResultError class that contains the std::string error message and int
errno.

It additionally has ostream operators to continue to allow printing
the error string directly to an ostream and also to pass the errno
through to another Result<T> class via Error() creation.

Lastly, it provides a new constructor for Result<T> for ResultError,
such that a Result<T> can be constructed from Result<U>::error().

Test: boot bullhead, init unit tests
Change-Id: Id9614b727cdabd2f5498b0da0e598e9aff7d9ae0
2017-08-23 11:04:32 -07:00
Tom Cherry
89bcc85edf init: use Result<T> for the parsing functions
Test: boot bullhead
Merged-In: I7f00c5f0f54dd4fe05df73e1d6a89b56d788e113
Change-Id: I7f00c5f0f54dd4fe05df73e1d6a89b56d788e113
2017-08-14 14:07:49 -07:00
Tom Cherry
557946e57c init: use Result<T> for builtin functions
We currently throw out the return values from builtin functions and
occasionally log errors with no supporting context.  This change uses
the newly introduced Result<T> class to communicate a successful result
or an error back to callers in order to print an error with clear
context when a builtin fails.

Example:

init: Command 'write /sys/class/leds/vibrator/trigger transient' action=init (/init.rc:245) took 0ms and failed: Unable to write to file '/sys/class/leds/vibrator/trigger': open() failed: No such file or directory

Test: boot bullhead
Merged-In: Idc18f331d2d646629c6093c1e0f2996cf9b42aec
Change-Id: Idc18f331d2d646629c6093c1e0f2996cf9b42aec
2017-08-14 14:07:39 -07:00
Tom Cherry
ede0d53850 Move Timer from init to libbase
Test: boot bullhead
Test: new libbase unit tests

Change-Id: Ic398a1daa1fe92c10ea7bc1e6ac3f781cee9a5b5
2017-07-10 09:28:24 -07:00
Wei Wang
eeab491efd init: Support custom shutdown actions
We have been seeing panics and errors during shutdown sequence in
some vendor's platform, and it is required to disable error handling
during shutdown.

This CL separates the shutdown request to execute another "shutdown"
trigger at the beginning of shutdown stage. And vendor can use this
trigger to add custom commands needed for shutting down gracefully.

Bug: 38203024
Bug: 62084631
Test: device reboot/shutdown
Change-Id: I3fac4ed59f06667d86e477ee55ed391cf113717f
2017-07-05 14:49:57 -07:00
Tom Cherry
81f5d3ebef init: create android::init:: namespace
With some small fixups along the way

Test: Boot bullhead
Test: init unit tests
Change-Id: I7beaa473cfa9397f845f810557d1631b4a462d6a
2017-06-23 13:21:20 -07:00
Tom Cherry
1c3a53f03c init: cleanup some string usage
1) property_set() takes const std::string& for both of its arguments,
   so stop using .c_str() with its parameters
2) Simplify a few places where StringPrintf() is used to concatenate strings
3) Use std::to_string() instead of StringPrintf() where it's better suited

Test: Boot bullhead
Test: init unit tests
Change-Id: I68ebda0e469f6230c8f9ad3c8d5f9444e0c4fdfd
2017-06-22 17:24:22 -07:00
Tom Cherry
d9ebf06117 Merge "init: rename 'Trigger' to 'Event' and convert to std::variant" 2017-04-25 21:44:19 +00:00
Tom Cherry
fe062055cb ueventd: replace ueventd_parser.cpp with init_parser.cpp
Previously init_parser.cpp was made generic and capable of parsing any
number of differently named 'sections' or prefixed lines.  We now use
these capabilities to do the parsing for ueventd.

Bug: 36250207
Bug: 33785894

Test: boot bullhead and ensure the right /dev nodes exist
      with the right permissions set
Test: verify no boot time difference
Change-Id: I698ca962d414f8135af32f6c9cd778841b2b8b53
2017-04-25 11:24:24 -07:00
Tom Cherry
26ed9cb706 init: rename 'Trigger' to 'Event' and convert to std::variant
The term 'trigger' should be used in 'Action' to indicate what causes
the 'Action' to be executed.

The term 'event' should be used in ActionManager's queue to indicate
a state change that is checked against the 'triggers' of an 'Action' to
see if it should execute.

Convert the previous Trigger class to std::variant, as the latter is
better suited for this use.

Change-Id: I2558367c8318b536aa69fcec93793f1c12857ef5
2017-04-25 17:14:23 +00:00
Tom Cherry
30a6f276fd init: clean up the SectionParser interface and Parser class
Remove the dependency on Action and Service from what should be a
generic Parser class.

Make ActionParser, ImportParser, and ServiceParser take a pointer to
their associated classes instead of accessing them through a
singleton.

Misc fixes to SectionParser Interface:
1) Make SectionParser::ParseLineSection() non-const as it always should
have been.
2) Use Rvalue references where appropriate
3) Remove extra std::string& filename in SectionParser::EndFile()
4) Only have SectionParser::ParseSection() as pure virtual

Document SectionParser.

Make ImportParser report the filename and line number of failed imports.

Make ServiceParser report the filename and line number of duplicated services.

Test: Boot bullhead

Change-Id: I86568a5b375fb4f27f4cb235ed1e37635f01d630
2017-04-21 18:26:40 -07:00
Tom Cherry
012c573e26 init: Stop combining actions
In the past, I had thought it didn't make sense to have multiple
Action classes with identical triggers within ActionManager::actions_,
and opted to instead combine these into a single action.  In theory,
it should reduce memory overhead as only one copy of the triggers
needs to be stored.

In practice, this ends up not being a good idea.

Most importantly, given a file with the below three sections in this
same order:

on boot
  setprop a b

on boot && property:true=true
  setprop c d

on boot
  setprop e f

Assuming that property 'true' == 'true', when the `boot` event
happens, the order of the setprop commands will actually be:

setprop a b
setprop e f
setprop c d

instead of the more intuitive order of:

setprop a b
setprop c d
setprop e f

This is a mistake and this CL fixes it.  It also documents this order.

Secondly, with a given 'Action' now spanning multiple files, in order
to keep track of which file a command is run from, the 'Command'
itself needs to store this.  Ironically to the original intention,
this increases total ram usage.  This change now only stores the file
name in each 'Action' instead of each 'Command'.  All in all this is a
negligible trade off of ram usage.

Thirdly, this requires a bunch of extra code and assumptions that
don't help anything else.  In particular it forces to keep property triggers
sorted for easy comparison, which I'm using an std::map for currently,
but that is not the best data structure to contain them.

Lastly, I added the filename and line number to the 'processing
action' LOG(INFO) message.

Test: Boot bullhead, observe above changes
Test: Boot sailfish, observe no change in boot time
Change-Id: I3fbcac4ee677351314e33012c758145be82346e9
2017-04-19 11:26:29 -07:00
Tom Cherry
3f5eaae526 init: more header cleanup
Remove includes of "log.h" that really want <android-base/logging.h>
Fix header include order
Remove headers included in .cpp files that their associated .h already includes
Remove some unused headers

Test: boot bullhead
Change-Id: I2b415adfe86a5c8bbe4fb1ebc53c7b0ee2253824
2017-04-06 18:06:34 -07:00
Tom Cherry
ccf23537ee init: replace property_get with its android::base equivalent
Slowly try to decouple property_service.cpp from the rest of init.

Test: Boot bullhead
Change-Id: I267ae0b057bca0bf657b97cb8bfbb18199282729
2017-03-29 10:07:54 -07:00
Tom Cherry
d8a7257b14 init: fix DumpState() logging
Fix two formatting issues in Action::DumpState(),

Old:
on ro.crypto.state=encrypted ro.crypto.type=file zygote-start
New:
on ro.crypto.state=encrypted && ro.crypto.type=file && zygote-start

Old:
on boot
  %sifup lo
  %shostname localhost
  %sdomainname localdomain
  %swrite /proc/sys/vm/overcommit_memory 1
New:
on boot
  ifup lo
  hostname localhost
  domainname localdomain
  write /proc/sys/vm/overcommit_memory 1

Also, now that we're importing many small rc files, it no longer makes
sense to call Parser::DumpState() after each import.  Therefore, move
the conditional to call Parser::DumpState() to after /init.rc and its
imports are parsed and after the late imports are parsed.

Test: Boot bullhead with DumpState() enabled and check the output
Change-Id: I0b81305b8938aa1a7133d7dd2055f34f47609cf9
2017-03-13 12:24:49 -07:00
Tom Cherry
2bc00140be init: enable C++17
Test: Boot bullhead
Change-Id: I40961ff765461e8aef211d27158ffb7c4be76493
2017-03-13 11:58:58 -07:00
Elliott Hughes
331cf2fb7c Replace the "coldboot" timeout with a property.
Also rename init's existing boot-time related properties so they're
all "ro.*" properties.

Example result:

  # Three properties showing when init started...
  [ro.boottime.init]: [5294587604]
  # ...how long it waited for ueventd...
  [ro.boottime.init.cold_boot_wait]: [646956470]
  # ...and how long SELinux initialization took...
  [ro.boottime.init.selinux]: [45742921]

  # Plus one property for each service, showing when it first started.
  [ro.boottime.InputEventFind]: [10278767840]
  [ro.boottime.adbd]: [8359267180]
  [ro.boottime.atfwd]: [10338554773]
  [ro.boottime.audioserver]: [10298157478]
  [ro.boottime.bootanim]: [9323670089]
  [ro.boottime.cameraserver]: [10299402321]
  [ro.boottime.cnd]: [10335931856]
  [ro.boottime.debuggerd]: [7001352774]
  [ro.boottime.debuggerd64]: [7002261785]
  [ro.boottime.drm]: [10301082113]
  [ro.boottime.fingerprintd]: [10331443314]
  [ro.boottime.flash-nanohub-fw]: [6995265534]
  [ro.boottime.gatekeeperd]: [10340355242]
  [ro.boottime.healthd]: [7856893380]
  [ro.boottime.hwservicemanager]: [7856051088]
  [ro.boottime.imscmservice]: [10290530758]
  [ro.boottime.imsdatadaemon]: [10358136702]
  [ro.boottime.imsqmidaemon]: [10289084872]
  [ro.boottime.installd]: [10303296020]
  [ro.boottime.irsc_util]: [10279807632]
  [ro.boottime.keystore]: [10305034093]
  [ro.boottime.lmkd]: [7863506714]
  [ro.boottime.loc_launcher]: [10324525241]
  [ro.boottime.logd]: [6526221633]
  [ro.boottime.logd-reinit]: [7850662702]
  [ro.boottime.mcfg-sh]: [10337268315]
  [ro.boottime.media]: [10312152687]
  [ro.boottime.mediacodec]: [10306852530]
  [ro.boottime.mediadrm]: [10308707999]
  [ro.boottime.mediaextractor]: [10310681177]
  [ro.boottime.msm_irqbalance]: [7862451974]
  [ro.boottime.netd]: [10313523104]
  [ro.boottime.netmgrd]: [10285009351]
  [ro.boottime.oem_qmi_server]: [10293329092]
  [ro.boottime.per_mgr]: [7857915776]
  [ro.boottime.per_proxy]: [8335121605]
  [ro.boottime.perfd]: [10283443101]
  [ro.boottime.qcamerasvr]: [10329644772]
  [ro.boottime.qmuxd]: [10282346643]
  [ro.boottime.qseecomd]: [6855708593]
  [ro.boottime.qti]: [10286196851]
  [ro.boottime.ril-daemon]: [10314933677]
  [ro.boottime.rmt_storage]: [7859105047]
  [ro.boottime.servicemanager]: [7864555881]
  [ro.boottime.ss_ramdump]: [8337634938]
  [ro.boottime.ssr_setup]: [8336268324]
  [ro.boottime.surfaceflinger]: [7866921402]
  [ro.boottime.thermal-engine]: [10281249924]
  [ro.boottime.time_daemon]: [10322006542]
  [ro.boottime.ueventd]: [5618663938]
  [ro.boottime.vold]: [7003493920]
  [ro.boottime.wificond]: [10316641073]
  [ro.boottime.wpa_supplicant]: [18959816881]
  [ro.boottime.zygote]: [10295295029]
  [ro.boottime.zygote_secondary]: [10296637269]

Bug: http://b/31800756
Test: boots
Change-Id: I094cce0c1bab9406d950ca94212689dc2e15dba5
2016-12-03 10:54:26 -08:00
Wei Wang
93df4e18a2 init: move empty string check to InitTriggers
Test: mma
Bug: 32838381
Change-Id: I69203734ef7d3640da75f3e3cbe9254bf468d916
2016-11-16 22:24:43 -08:00
Wei Wang
d67a4abc64 init: fix undefined behavior in ExecuteCommand
ExecuteCommand may change command_ vector which leads undefined behavior
This bug is found when adding logs in ExecuteCommand printing our Command class fields

Bug: 32838381
Test: on emulator
Change-Id: I96468bd2192ca80013871a3a6ac4132149363fff
2016-11-16 15:46:19 -08:00
Wei Wang
8b1d526a72 Revert "Revert "init: warn slow action""
This reverts commit 1802d11cc7.

Test: grep init log
Bug: 32712851
2016-11-15 23:58:55 -08:00
Treehugger Robot
9b1d5e15ef Merge "init: fix BuildTriggersString for empty string" 2016-11-15 17:23:56 +00:00
Wei Wang
69b9b36c11 init: fix BuildTriggersString for empty string
behavior is undefined if pop_back() on empty std::string

Test: grep init log
Bug: 32712851
Bug: 32838381
Change-Id: I5bfac2fb275036abd0158b78df14019d2e82716d
2016-11-14 20:20:48 -08:00
Nick Desaulniers
1802d11cc7 Revert "init: warn slow action"
This reverts commit b1a309ac1f.

Bug: 32712851
Bug: 32838381
Change-Id: Ib4c47de5ea5b0bad765a43cbff9f73d9978729d4
2016-11-15 00:53:00 +00:00
Wei Wang
b1a309ac1f init: warn slow action
Slow action that takes longer than 50ms will be warned to user

Test: grep init log
Bug: 32712851
Change-Id: I3a6a881a8dee1807270343b511a47c76dd230392
2016-11-09 15:19:11 -08:00
Elliott Hughes
7bc87a5a78 Move init's kernel logging into libbase.
This will let other stuff (such as adbd and recovery) use it too.

Bug: http://b/28467098
Change-Id: Idab51f438ed3edd6fe65a56c4b396eaff5f3833e
2016-08-04 16:09:39 -07:00
Elliott Hughes
35f5d04620 Fix early init logging.
Remove the /dev/__kmsg__ workarounds (which can then be removed
from sepolicy), and fix confusion in the translation between
android-base logging and kernel logging priorities (in particular,
where 'notice' comes in the hierarchy).

Bug: http://b/30317429
Change-Id: I6eaf9919904b6b55bc402c20bf1a4ae269014bc7
Test: adb shell dmesg | grep init
2016-07-26 09:32:33 -07:00
Elliott Hughes
f86b5a6b90 Move init to libbase logging.
Change-Id: Ibfbefeff587a69e948978a037c555fd12a5ade6a
2016-06-27 08:11:31 -07:00
Chih-Hung Hsieh
1c563d96f0 Fix google-explicit-constructor warnings.
Bug: 28341362
Change-Id: I4504e98a8db31e0edcbe63c23f9af43eb13e9d86
2016-04-29 15:44:04 -07:00