Commit Graph

272 Commits (139192140c8737b5b4abd1a08b9cf918a653e854)

Author SHA1 Message Date
Sam Lantinga 6d9c4f6c6c Added support for the wired Amazon Luna gamepad on Android 2021-03-26 15:07:10 -07:00
Sam Lantinga f5e9c5b7e0 Chromebooks support relative mouse motion now 2021-02-21 11:03:25 -08:00
Amir 1a924bc0bb add SDL_AndroidShowToast for https://developer.android.com/reference/android/widget/Toast 2021-02-20 23:05:09 -08:00
Jordan Christiansen 7032539785 Disabled Bluetooth if BLE is not supported
BluetoothManager is supported for Android API 18+. On older versions, skip
Bluetooth instead of crashing.
2021-01-07 19:33:12 -06:00
Sam Lantinga cdd397118f Fixed the Xbox Series X controller showing up twice on Android 2020-12-15 14:57:49 -08:00
Sylvain Becker 311ae829c7 Android: keep compatibility with older JDK 2020-10-28 14:03:05 +01:00
Sylvain Becker 97cf314526 Android: apply code simplications found with lint / Android Studio 2020-10-27 21:14:49 +01:00
Sylvain Becker 0360987f45 Android: fix deprecated onCreateDialog() methods 2020-10-24 20:31:04 +02:00
Sylvain Becker 967041681b Android: fix Clipboard deprecated methods 2020-10-24 15:36:05 +02:00
Sylvain Becker b7b8ef59a3 Fixed bug 5307 - Crash when joysticks hats number is odd (Thanks Sockmonsters!) 2020-10-07 17:32:07 +02:00
Sylvain Becker bffbc7e316 Android: better readibility for pollHapticDevices() 2020-10-07 14:55:23 +02:00
Sylvain Becker 20c070d869 Android: better readibility for pollInputDevices()
and move isDeviceSDLJoystick() test at first since there are
always non-joystick devices present.
2020-10-07 14:41:37 +02:00
Sylvain Becker a70bb58d4b Android: fix joystick allocation that can be never used 2020-10-05 14:09:31 +02:00
Sylvain Becker 2e38c94950 Fix bug 5303 - Touch/Mouse events simulation doesn't work on Android 11 2020-10-05 09:56:03 +02:00
Sylvain Becker 0467e332af Android: small change to access to device diagonal value 2020-10-01 15:11:28 +02:00
Sylvain Becker 62b029f33b Android: missing import class Uri 2020-10-01 14:43:59 +02:00
Sylvain Becker dd55bfe89c Android: add helper function to open an URL/URI (see bug 2783) 2020-10-01 14:41:09 +02:00
Sylvain Becker 7ad71563ce Android: be sure shared libraries are loaded in onConfigurationChanged()
This could fix a rare crash if:
- onConfigurationChanged is called before onCreate();
or
 shared libraries failed to load and onConfigurationChanged() is called
2020-09-25 10:42:07 +02:00
Sylvain Becker 96d555e25a Android: remove un-needed java import (bug 4297) 2020-08-17 20:09:01 +02:00
Sylvain Becker 965b466ee8 Fixed bug 4297 - Android StrictMode policy. Remove APK expansion support
"In the second half of 2021, new apps will be required to publish with the Android App Bundle on Google Play"
(see https://developer.android.com/guide/app-bundle)
And "Android App Bundles don't support APK expansion (*.obb) files".
2020-08-17 19:50:20 +02:00
Sam Lantinga d0947c1483 Fixed exception if getManifestEnvironmentVariables() is called without a current SDL activity 2020-06-04 12:30:25 -07:00
Sam Lantinga 68e1731e02 Don't bother logging security exception getting the device serial number
This can happen anytime we haven't opened the device yet
2020-05-29 15:40:17 -07:00
Sockmonsters eea450bc99 - Added exception handler for the new SecurityException in USBDevice getSerialNumber 2020-05-29 15:37:03 -07:00
Sylvain Becker 33642b47b2 Android: robustness if locale failed to be detected at start 2020-05-08 21:50:23 +02:00
Sylvain Becker 2491f16f85 Android: send SDL_LOCALECHANGED when locale changes 2020-05-08 21:40:28 +02:00
Sam Lantinga beab15b09e Added additional logging to track down why the NVIDIA controller doesn't send the back button 2020-04-27 19:12:02 -07:00
Sam Lantinga 37faac0d81 Fixed java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.WindowManager android.app.Activity.getWindowManager()' on a null object reference 2020-03-05 08:43:16 -08:00
Sam Lantinga dc54add5e0 Added some extra permissions and features likely to be used by SDL applications 2020-02-14 18:21:58 -08:00
Sam Lantinga 14bf532df3 Fixed opening audio on Android from the Steam Link shell activity 2020-02-13 16:10:52 -08:00
Sam Lantinga 4bb95e8403 Implemented OpenSL-ES audio recording on Android 2020-02-11 16:14:02 -08:00
Sam Lantinga 64c58b9f19 Fixed NullPointerException 2020-02-07 20:20:37 -08:00
Sam Lantinga c9c89783cb Miscellaneous pending fixes 2020-01-29 20:09:08 -08:00
Sam Lantinga 598cf69475 Fixed member order to make more sense 2020-01-28 21:41:13 -08:00
Sam Lantinga 43b377b077 Fixed wired PS4 controller support on Android 2020-01-28 17:11:17 -08:00
Sam Lantinga ce7c51a9cc Always release devices in onPause in case we're going to be force stopped, and for consistency with interacting with other activities that might use the controller 2020-01-26 00:37:48 -08:00
Sam Lantinga 43aa1fa9e7 Added support for detecting previously unknown Xbox 360 and Xbox One controllers using the HIDAPI driver with libusb and Android 2020-01-18 11:21:14 -08:00
Sylvain Becker d52ba78b29 Fixed bug 4246 - Android: orientation between portrait<->landscape doesn't work
Improve handling of landscape/portrait orientation. Promote to SCREEN_ORIENTATION_SENSOR_* when needed.
Android window can be somehow resizable.
If SDL_WINDOW_RESIZABLE is set, window size change is allowed, for instance when orientation changes (provided the hint allows it).
2020-01-17 12:04:18 +01:00
Sam Lantinga 1d321850b6 Added support for claiming individiual interfaces on USB devices on Android
This is needed for supporting multiple wireless Xbox 360 controllers
2020-01-13 15:35:52 -08:00
Sam Lantinga a7bf6af8c4 The Amlogic TVB-906X is Android TV 2020-01-11 04:34:23 -08:00
Sylvain Becker f050309ee9 Android: fix IllegalStateException in onBackPressed()
Rare exception, not catch-able, which appears when the activity gets in a broken
state.

java.lang.IllegalStateException:
  at android.app.FragmentManagerImpl.checkStateLoss (FragmentManagerImpl.java:1323)
  at android.app.FragmentManagerImpl.popBackStackImmediate (FragmentManagerImpl.java:493)
  at android.app.Activity.onBackPressed (Activity.java:2215)
  at org.libsdl.app.SDLActivity.onBackPressed (SDLActivity.java)
  at android.app.Activity.onKeyUp (Activity.java:2193)
  at android.view.KeyEvent.dispatch (KeyEvent.java:2685)
  at android.app.Activity.dispatchKeyEvent (Activity.java:2423)
  at org.libsdl.app.SDLActivity.dispatchKeyEvent (SDLActivity.java)
2019-12-20 15:58:59 +01:00
Sam Lantinga 15d30298cf Added support for wireless Xbox 360 controllers using the HIDAPI driver 2019-12-19 15:01:32 -08:00
Sylvain Becker 5d5a56717f Fixed bug 4906 - Pressing Back button terminates app after SDL_StartTextInput 2019-12-19 13:54:03 +01:00
Sam Lantinga 7b2826f6c2 Added Android support for the Hyperkin X91 and the SteelSeries Stratus Duo 2019-12-17 12:03:57 -08:00
Sam Lantinga d4e1c79720 Backed out changeset 36b79874a9c8, which fixed bug 4775
This change broke individual key events, so I'm reverting the change until we can investigate a better fix.
2019-11-27 17:17:03 -08:00
Sylvain Becker 59352cea8b Fixed bug 4775 - Japanese on Android, remove inputtype PASSWORD (Thanks Tamo!) 2019-10-23 11:25:16 +02:00
Sylvain Becker 0a9c74aa9a Fixed bug 3918 - HIDAPI, CMake support for android project 2019-08-27 11:38:43 +02:00
Sylvain Becker 7f9016f265 Android: remove tabs/indent 2019-08-15 20:38:25 +02:00
Sylvain Becker 412775f5a8 Android: SDL_image/SDL_mixer/SDL_ttf partially compiling with CMake (bug 3918) 2019-08-13 16:00:08 +02:00
Sylvain Becker 155087d106 Fixed bug 3918 - CMake support for android project 2019-08-11 15:23:37 +02:00
Sam Lantinga e92fe23c83 Fix nullptr crash on android
nullcheck the device coming back from InputDevice.getDevice(deviceId) in new code added to sdlactivity.onkey.


java.lang.NullPointerException:
  at org.libsdl.app.SDLSurface.onKey (SDLActivity.java:1793)
  at android.view.View.dispatchKeyEvent (View.java:13321)
  at android.view.ViewGroup.dispatchKeyEvent (ViewGroup.java:1912)
  at android.view.ViewGroup.dispatchKeyEvent (ViewGroup.java:1912)
  at android.view.ViewGroup.dispatchKeyEvent (ViewGroup.java:1912)
  at android.view.ViewGroup.dispatchKeyEvent (ViewGroup.java:1912)
  at com.android.internal.policy.DecorView.superDispatchKeyEvent (DecorView.java:685)
  at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent (PhoneWindow.java:1869)
  at android.app.Activity.dispatchKeyEvent (Activity.java:3447)
  at org.libsdl.app.SDLActivity.dispatchKeyEvent (SDLActivity.java:496)

@dang @saml @dave
2019-08-02 17:20:00 -07:00
Sylvain Becker f994da0ef0 Fixed bug 4702 - Android back button does not send SDL_KEYDOWN event
fallback when event.getSource() is SOURCE_UNKNOWN
2019-07-03 13:37:54 +02:00
Sylvain Becker 5418d41626 Android: prevent ignoring surfaceChanged() in MultiWindow 2019-06-18 11:35:30 +02:00
Sylvain Becker 4392c6ff14 Android: fix coordinates for Surface.ROTATION_180
https://discourse.libsdl.org/t/android-screen-orientation-issues-2-0-9/26262
2019-06-11 11:01:15 +02:00
Sylvain Becker 45a3dd171d Android: revert wrong fix typo calling onBackPressed() (Bug 4657) 2019-06-11 10:19:26 +02:00
Sylvain Becker f9a9193e2c Android: add MinimizeWindow function (Bug 4580, 4657)
shouldMinimizeOnFocusLoss is un-activated (return false)
2019-06-10 21:58:03 +02:00
Sylvain Becker 3f4e189b27 Android: fix typo calling onBackPressed() (Bug 4657) 2019-06-10 21:41:22 +02:00
Sam Lantinga 8b57331e71 Fixed hiding the Android virtual keyboard when the return key is pressed 2019-05-23 11:05:43 -07:00
Sylvain Becker f91b87859c Android: minimum size for IME, so that it takes focus
In API 28, 0 width views can't take focus, so if someone tries to position the IME without setting a width, they'll stop getting text events.

Tested on Android 9: with a 0 size, it would send correctly letters a, b, c, etc. but not numbers.
2019-05-23 09:08:40 +02:00
Sam Lantinga 1a38853e02 Fixed bug 4566 - Hot-plugging Bluetooth controller causes force-quit on Android
Anthony @ POW Games

I tried adding different configChanges and sure enough, "navigation" worked! Now bluetooth controllers hot-plug nicely. So shall we add it as a default to the AndroidManifest.xml?

Funny that this is how this activity is described:

	"navigation" The navigation type (trackball/dpad) has changed. (This should never normally happen.)

I think the reason behind this is because the bluetooth game controller I was testing doubles-up as a keyboard, which probably comes with a DPAD? It's a MOCUTE-032X_B63-88CE
2019-04-24 12:53:15 -07:00
Sam Lantinga f5252530d2 Change my previous fix based on feedback from dev @saml 2019-04-23 14:08:14 -07:00
Sam Lantinga ecce803d54 Fix compile errors I hit when building org.libsdl in source2 (part 2 of 2) @saml 2019-04-23 12:59:28 -07:00
Sam Lantinga 45b5453b16 Fix compile errors I hit when building org.libsdl in source2 (part 1 of 2) 2019-04-23 12:59:20 -07:00
Sam Lantinga 9950271bb6 Fixed bug 4580 - Android 8: immersive fullscreen notification causes flickering between fullscreen and non-fullscreen and app is unresponsive
Sylvain 2019-04-18 21:22:59 UTC

Changes:
- SDL_WINDOWEVENT_FOCUS_GAINED and SDL_WINDOWEVENT_FOCUS_LOST are sent when the java method onWindowFocusChanged() is called.

- If we have support for MultiWindow (eg API >= 24), SDL event loop is blocked/un-blocked (or simply egl-backed-up or not), when java onStart()/onStop() are called.

- If not, this behaves like now, SDL event loop is blocked/un-blocked when onPause()/onResume() are called.

So if we have two app on screen and switch from one to the other, only FOCUS events are sent (and onPause()/onResume() are called but empty. onStart()/onStop() are not called).
The SDL app, un-focused, would still continue to run and display frames (currently the App would be displayed, but paused).
Like a video player app or a chronometer that would still be refreshed, even if the window hasn't the focus.
It should work also on ChromeBooks (not tested), with two apps opened at the same time.


I am not sure this fix Dan's issue. Because focus lost event triggers Minimize function (which BTW is not provided on android).
https://hg.libsdl.org/SDL/file/bb41b3635c34/src/video/SDL_video.c#l2653
https://hg.libsdl.org/SDL/file/bb41b3635c34/src/video/SDL_video.c#l2634

So, in addition, it would need to add by default SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS to 0.
So that the lost focus event doesn't try to minimize the window. And this should fix also the issue.
2019-04-22 16:19:52 -07:00
Sam Lantinga cf87d5764d Explicitly load hidapi as a dependency of the SDL library
This fixes loading on Android 4.2
2019-04-16 20:00:14 -07:00
Sylvain Becker bfdd0b228a Android: remove SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH
java layer runs as if separate mouse and touch was 1,
Use SDL_HINT_MOUSE_TOUCH_EVENTS and SDL_HINT_TOUCH_MOUSE_EVENTS
for generating synthetic touch/mouse events
2019-04-04 17:01:02 +02:00
Sylvain Becker 3bc1a8b619 Android: minor comment update 2019-03-13 14:08:21 +01:00
Sylvain Becker 9d10c73853 Android: remove duplicate code in SDLGenericMotionListener_API24
and use parent method
2019-01-17 16:30:19 +01:00
Sylvain Becker 55838d8bd6 Android: remove another hard-coded constant for Samsung DeX (no op!) 2019-01-17 14:59:46 +01:00
Sylvain Becker 56f4a711e3 Android: minor change in the evaluation of SOURCE_CLASS_JOYSTICK (no op!)
InputDevice.SOURCE_CLASS_* are one bit
More readable to check that the source has this class_joystick set,
compared to the other statements, where the source is gamepad or dpad.
(Clean-up from bug 3958)
2019-01-17 13:42:13 +01:00
Sylvain Becker 8f828a8e1b Android: remove hard-coded constant for Samsung DeX (no op!)
12290 = 0x3002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN

SOURCE_MOUSE            Constant Value: 8194 (0x00002002)
SOURCE_TOUCHSCREEN      Constant Value: 4098 (0x00001002)
SOURCE_CLASS_POINTER    Constant Value: 2    (0x00000002)

https://developer.android.com/reference/android/view/InputDevice.html
2019-01-17 12:25:19 +01:00
Sylvain Becker e5f8801f55 Android: prevent concurrency in Android_SetScreenResolution() when exiting
by checking Android_Window validity

- SDLThread: user application is exiting:
    SDL_VideoQuit() and clearing SDL_GetVideoDevice()

- ActivityThread is changing orientation/size
    surfaceChanged() > Android_SetScreenResolution() > SDL_GetVideoDevice()

- Separate function into Android_SetScreenResolution() and Android_SendResize(),
    formating, and mark Android_DeviceWidth/Heigh as static
2019-01-17 11:05:05 +01:00
Sylvain Becker 6690a46941 Android: also update APP_PLATFORM to android-16 in Application.mk
https://hg.libsdl.org/SDL/rev/701c83eeb6e7
https://hg.libsdl.org/SDL/rev/0a69e71b715a
2019-01-17 09:28:30 +01:00
Sylvain Becker 291f6006a1 Android: merge SDLJoystickHandler_API12 and SDLJoystickHandler_API16 2019-01-16 09:22:20 +01:00
Sylvain Becker a86754167c Android: remove trailing spaces 2019-01-16 09:12:31 +01:00
Sylvain Becker d86de288d4 Android: remove old code after Android-16 has been set as minimum requirement 2019-01-16 09:11:13 +01:00
Sylvain Becker dc263450ff Android: create Pause/ResumeSem semaphore at higher level than CreateWindow()
- If you call onPause() before CreateWindow(), SDLThread will run in infinite loop in background.

- If you call onPause() between a DestroyWindow() and a new CreateWindow(), semaphores are invalids.

SDLActivity.java: the first resume() starts the SDLThread, don't call
nativeResume() as it would post ResumeSem. And the first pause would
automatically be resumed.
2019-01-14 23:33:48 +01:00
Sylvain Becker ae41831e0d Android: minor, remove static attributes, move mIsSurfaceReady to SDLSurface 2019-01-14 21:34:12 +01:00
Sylvain Becker 42e18bd0c2 Android: fix bad merge from previous commit 2019-01-11 14:25:32 +01:00
Sylvain Becker 7a1d1baefc Android: add name for Touch devices and simplification, from bug 3958 2019-01-10 21:40:57 +01:00
Sylvain Becker d23c2f07e3 Fixed bug 3930 - Android, set thread priorities and names
SDLActivity thread priority is unchanged, by default -10 (THREAD_PRIORITY_VIDEO).

SDLAudio thread priority was -4 (SDL_SetThreadPriority was ignored) and is now -16 (THREAD_PRIORITY_AUDIO).

SDLThread thread priority was 0 (THREAD_PRIORITY_DEFAULT) and is -4 (THREAD_PRIORITY_DISPLAY).
2019-01-10 18:05:56 +01:00
Sylvain Becker 0e0e0272b8 Android: remove deprecated PixelFormat in surfaceChanged()
Can be check by adding in build.grable:

gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
    }
}

SDLActivity.java:1691: warning: [deprecation] A_8 in PixelFormat has been deprecated
        case PixelFormat.A_8:
SDLActivity.java:1694: warning: [deprecation] LA_88 in PixelFormat has been deprecated
SDLActivity.java:1697: warning: [deprecation] L_8 in PixelFormat has been deprecated
SDLActivity.java:1700: warning: [deprecation] RGBA_4444 in PixelFormat has been deprecated
SDLActivity.java:1704: warning: [deprecation] RGBA_5551 in PixelFormat has been deprecated
SDLActivity.java:1716: warning: [deprecation] RGB_332 in PixelFormat has been deprecated
2019-01-10 16:04:52 +01:00
Sylvain Becker 5c11e5ef92 Android: some simplification, don't need mExitCalledFromJava 2019-01-10 15:48:43 +01:00
Sylvain Becker 66fbfe1d00 Android: nativeQuit for SDLActivity thread
- destroy Android_ActivityMutex
- display any SDL error message that may have occured in this thread,
  since SDL_GetError() is thread specific, and user has no access to it.
2019-01-10 15:43:07 +01:00
Sylvain Becker dad8161103 Android: only send Quit event to SDLThread if it's not already terminated
And it avoids reporting errors using Android_Pause/ResumeSem that are NULL.
2019-01-10 15:35:46 +01:00
Sylvain Becker 61d37de099 Android: un-needed transition to Pause state.
- Don't need to go into Pause state, since onPause() has been called before.
- Don't need to call nativePause is SDLThread is already ended
2019-01-10 15:29:37 +01:00
Sylvain Becker 8dd915507e Android: prevent a dummy error message sending SDL_DISPLAYEVENT_ORIENTATION
In the usual case, first call to onNativeOrientationChanged() is done before
SDL has been initialised and would just set an error message
"Video subsystem has not been initialized" without sending the event.
2019-01-09 23:19:26 +01:00
Sylvain Becker 68c0e69f0a Android: native_window validity is guaranteed between surfaceCreated and Destroyed
It's currently still available after surfaceDestroyed().
And available (but invalid) between surfaceCreated() and surfaceChanged().

Which means ANativewindow_getWidth/Height/Format() fail in those cases.

https://developer.android.com/reference/android/view/SurfaceHolder.html#getSurface()
2019-01-09 22:41:52 +01:00
Sylvain Becker 59df6d6b13 Android: don't allow multiple instance of SDLActivity
Default launch mode (standard) allows multiple instances of the SDLActivity.
( https://developer.android.com/guide/topics/manifest/activity-element#lmode )

Not sure this is intended in SDL as this doesn't work. There are static
 variables in Java, in C code which make this impossible (allow one android_window) and
 also Audio print errors.

There is also some code added in onDestroy as if it would be able to
re-initialize: https://hg.libsdl.org/SDL/rev/27686adb08c3

Bug Android activity life-cycle seems to show there is not transition to get out
of onDestroy()
https://developer.android.com/reference/android/app/Activity#ActivityLifecycle

( can be tested with "adb shell am start  my.package.org/.MainActivity"
  and "adb shell am start -n  my.package.org/.MainActivity" )

Send me a message if there are real use-case for this !
2019-01-07 17:06:50 +01:00
Sylvain Becker 911f1d3e67 Android: remove SURFACE_TYPE_GPU, deprecated in API level 5.
https://developer.android.com/reference/android/view/SurfaceHolder

This constant was deprecated in API level 5. this is ignored, this value is set automatically when needed.
2019-01-05 22:49:50 +01:00
Sylvain Becker a95f91bcea Fixed bug 3250 - Wrong backbuffer pixel format on Android, keep getting RGB_565
Use the egl format to reconfigure java SurfaceView holder format.
If there is a change, it triggers a surfaceDestroyed/Created/Change sequence.
2019-01-02 18:06:33 +01:00
Sylvain Becker a02998a292 Android: make sure surfaceChanged try to enter into 'resumed' state. 2019-01-02 17:41:33 +01:00
Sylvain Becker 4d2b5c791e Fixed bug 4424 - Android windowed mode is broken (Thanks Jonas Thiem!) 2019-01-02 17:08:01 +01:00
Sam Lantinga cc39c7a0cb Fixed bug 4320 - Android remove reflection for HIDDeviceBLESteamController
Sylvain

Uneeded use of reflection to access connectGatt method in HIDDeviceBLESteamController.java

The method is API 23

https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback,%20int)
2018-11-02 17:25:00 -07:00
Sam Lantinga 67a94893c0 Fixed bug 4319 - Android remove reflection for PointerIcon
Sylvain

Since SDL2 min requirement is Android SDK 26, and PointerIcon is 24. We don't need reflection to access it.
2018-11-02 17:22:15 -07:00
Sam Lantinga e381a1599d Updated Android project files and documentation 2018-10-28 10:31:06 -07:00
Sam Lantinga b699ddc0a9 Fixed reinitializing the SDL joystick subsystem on Android 2018-10-23 12:40:25 -07:00
Sam Lantinga d7fa11204f Change our fullscreen wait logic to only wait if we need to. (thanks Rachel!) 2018-10-22 14:55:47 -07:00
Sam Lantinga e6068b5b15 Handle failure to load hidapi gracefully 2018-10-22 14:55:45 -07:00
Sam Lantinga 3e3ce6e95c Fixed bug 4318 - Android move Haptic code to API26 class
Sylvain

- Create SDLHapticHandler_API26
- No need of reflection since SDL2 compile with Android 26 as a min requirement.
- remove spaces
2018-10-16 15:00:43 -07:00
Sam Lantinga b0c48dd9dd Support vibration magnitude on Android 8.0 (thanks Rachel!) 2018-10-16 08:29:27 -07:00