mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-04-28 12:17:57 +03:00
Merge branch 'Mis012/mr' into 'master'
misc additions See merge request android_translation_layer/android_translation_layer!151
This commit is contained in:
commit
536aa8e7ed
58 changed files with 2866 additions and 162 deletions
|
@ -3,30 +3,34 @@
|
|||
#include "../defines.h"
|
||||
#include "../generated_headers/android_media_SoundPool.h"
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_android_media_SoundPool_native_1constructor(JNIEnv *env, jclass) {
|
||||
GArray *sound_pool_array = g_array_new(FALSE, FALSE, sizeof(GtkMediaStream *));
|
||||
return _INTPTR(sound_pool_array);
|
||||
JNIEXPORT jlong JNICALL Java_android_media_SoundPool_native_1constructor(JNIEnv *env, jclass)
|
||||
{
|
||||
GArray *sound_pool_array = g_array_new(FALSE, FALSE, sizeof(GtkMediaStream *));
|
||||
return _INTPTR(sound_pool_array);
|
||||
}
|
||||
|
||||
static void on_prepared(GtkMediaStream *media_stream) {
|
||||
// play once muted to ensure file is fully loaded
|
||||
gtk_media_stream_set_muted(media_stream, TRUE);
|
||||
static void on_prepared(GtkMediaStream *media_stream)
|
||||
{
|
||||
// play once muted to ensure file is fully loaded
|
||||
gtk_media_stream_set_muted(media_stream, TRUE);
|
||||
gtk_media_stream_play(media_stream);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_android_media_SoundPool_nativeLoad(JNIEnv *env, jclass, jlong pool, jstring path) {
|
||||
GArray *sound_pool_array = _PTR(pool);
|
||||
JNIEXPORT jint JNICALL Java_android_media_SoundPool_nativeLoad(JNIEnv *env, jclass, jlong pool, jstring path)
|
||||
{
|
||||
GArray *sound_pool_array = _PTR(pool);
|
||||
const char* nativePath = (*env)->GetStringUTFChars(env, path, NULL);
|
||||
GtkMediaStream *media_stream = gtk_media_file_new_for_filename(nativePath);
|
||||
g_signal_connect(media_stream, "notify::prepared", G_CALLBACK(on_prepared), NULL);
|
||||
g_signal_connect(media_stream, "notify::prepared", G_CALLBACK(on_prepared), NULL);
|
||||
(*env)->ReleaseStringUTFChars(env, path, nativePath);
|
||||
return g_array_append_val(sound_pool_array, media_stream)->len - 1;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_android_media_SoundPool_nativePlay(JNIEnv *env, jclass, jlong pool, jint soundID) {
|
||||
JNIEXPORT jint JNICALL Java_android_media_SoundPool_nativePlay(JNIEnv *env, jclass, jlong pool, jint soundID)
|
||||
{
|
||||
GArray *sound_pool_array = _PTR(pool);
|
||||
GtkMediaStream *media_stream = g_array_index(sound_pool_array, GtkMediaStream *, soundID);
|
||||
gtk_media_stream_set_muted(media_stream, FALSE);
|
||||
GtkMediaStream *media_stream = g_array_index(sound_pool_array, GtkMediaStream *, soundID);
|
||||
gtk_media_stream_set_muted(media_stream, FALSE);
|
||||
gtk_media_stream_play(media_stream);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,12 @@ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeData(
|
|||
return ResXMLParser_getAttributeData(parser, index);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeName(JNIEnv *env, jclass this, jlong parser_ptr, jint index)
|
||||
{
|
||||
struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr);
|
||||
return ResXMLParser_getAttributeNameID(parser, index);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_content_res_XmlBlock_nativeDestroyParseState(JNIEnv *env, jobject this, jlong parser_ptr)
|
||||
{
|
||||
struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr);
|
||||
|
|
|
@ -217,7 +217,7 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValu
|
|||
* Signature: (JJII[IIJJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyStyle
|
||||
(JNIEnv *, jclass, jlong, jlong, jint, jint, jintArray, jint, jlong, jlong);
|
||||
(JNIEnv *, jobject, jlong, jlong, jint, jint, jintArray, jint, jlong, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_content_res_AssetManager
|
||||
|
@ -225,7 +225,7 @@ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyStyle
|
|||
* Signature: (JII[I[I[I[I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs
|
||||
(JNIEnv *, jclass, jlong, jint, jint, jintArray, jintArray, jintArray, jintArray);
|
||||
(JNIEnv *, jobject, jlong, jint, jint, jintArray, jintArray, jintArray, jintArray);
|
||||
|
||||
/*
|
||||
* Class: android_content_res_AssetManager
|
||||
|
@ -321,7 +321,7 @@ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_deleteTheme
|
|||
* Signature: (JIZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyThemeStyle
|
||||
(JNIEnv *, jclass, jlong, jint, jboolean);
|
||||
(JNIEnv *, jobject, jlong, jint, jboolean);
|
||||
|
||||
/*
|
||||
* Class: android_content_res_AssetManager
|
||||
|
@ -329,7 +329,7 @@ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyThemeStyle
|
|||
* Signature: (JJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_copyTheme
|
||||
(JNIEnv *, jclass, jlong, jlong);
|
||||
(JNIEnv *, jobject, jlong, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_content_res_AssetManager
|
||||
|
|
|
@ -453,14 +453,6 @@ JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeGetPointerProperties
|
|||
JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeScale
|
||||
(JNIEnv *, jclass, jint, jfloat);
|
||||
|
||||
/*
|
||||
* Class: android_view_MotionEvent
|
||||
* Method: nativeTransform
|
||||
* Signature: (ILandroid/graphics/Matrix;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_view_MotionEvent_nativeTransform
|
||||
(JNIEnv *, jclass, jint, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -231,6 +231,14 @@ JNIEXPORT void JNICALL Java_android_view_ViewGroup_native_1drawChildren
|
|||
JNIEXPORT void JNICALL Java_android_view_ViewGroup_native_1drawChild
|
||||
(JNIEnv *, jobject, jlong, jlong, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_view_ViewGroup
|
||||
* Method: native_dispatchTouchEvent
|
||||
* Signature: (JLandroid/view/MotionEvent;DD)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_android_view_ViewGroup_native_1dispatchTouchEvent
|
||||
(JNIEnv *, jobject, jlong, jobject, jdouble, jdouble);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,22 @@ JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1showAsDropDown
|
|||
JNIEXPORT jboolean JNICALL Java_android_widget_PopupWindow_native_1isShowing
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: native_setTouchable
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setTouchable
|
||||
(JNIEnv *, jobject, jlong, jboolean);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: native_setTouchModal
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setTouchModal
|
||||
(JNIEnv *, jobject, jlong, jboolean);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: native_dismiss
|
||||
|
@ -65,19 +81,43 @@ JNIEXPORT void JNICALL Java_android_widget_PopupWindow_setOnDismissListener
|
|||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: setWidth
|
||||
* Signature: (I)V
|
||||
* Method: native_setWidth
|
||||
* Signature: (JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_setWidth
|
||||
(JNIEnv *, jobject, jint);
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setWidth
|
||||
(JNIEnv *, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: setHeight
|
||||
* Signature: (I)V
|
||||
* Method: native_setHeight
|
||||
* Signature: (JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_setHeight
|
||||
(JNIEnv *, jobject, jint);
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setHeight
|
||||
(JNIEnv *, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: native_getWidth
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_android_widget_PopupWindow_native_1getWidth
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: native_getHeight
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_android_widget_PopupWindow_native_1getHeight
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_widget_PopupWindow
|
||||
* Method: native_isTouchable
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_android_widget_PopupWindow_native_1isTouchable
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -14,12 +14,13 @@ static void location_updated (
|
|||
gchar* description,
|
||||
gint64 timestamp_s,
|
||||
gint64 timestamp_ms,
|
||||
JavaVM *jvm
|
||||
) {
|
||||
JavaVM *jvm)
|
||||
{
|
||||
JNIEnv *env;
|
||||
(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6);
|
||||
jclass class = (*env)->FindClass(env, "android/location/LocationManager");
|
||||
(*env)->CallStaticVoidMethod(env, class, _STATIC_METHOD(class, "locationUpdated", "(DDD)V"), latitude, longitude, heading);
|
||||
jlong timestamp = timestamp_s * 1000 + timestamp_ms;
|
||||
(*env)->CallStaticVoidMethod(env, class, _STATIC_METHOD(class, "locationUpdated", "(DDDDDDJ)V"), latitude, longitude, altitude, accuracy, speed, heading, timestamp);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_location_LocationManager_nativeGetLocation(JNIEnv *env, jobject) {
|
||||
|
|
|
@ -132,6 +132,7 @@ void set_up_handle_cache(JNIEnv *env)
|
|||
handle_cache.view.getScrollY = _METHOD(handle_cache.view.class, "getScrollY", "()I");
|
||||
handle_cache.view.performClick = _METHOD(handle_cache.view.class, "performClick", "()Z");
|
||||
handle_cache.view.onTouchEvent = _METHOD(handle_cache.view.class, "onTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||
handle_cache.view.onTouchEventInternal = _METHOD(handle_cache.view.class, "onTouchEventInternal", "(Landroid/view/MotionEvent;)Z");
|
||||
handle_cache.view.dispatchTouchEvent = _METHOD(handle_cache.view.class, "dispatchTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||
handle_cache.view.onInterceptTouchEvent = _METHOD(handle_cache.view.class, "onInterceptTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||
handle_cache.view.layoutInternal = _METHOD(handle_cache.view.class, "layoutInternal", "(II)V");
|
||||
|
@ -143,6 +144,9 @@ void set_up_handle_cache(JNIEnv *env)
|
|||
handle_cache.view.dispatchKeyEvent = _METHOD(handle_cache.view.class, "dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z");
|
||||
handle_cache.view.onKeyDown = _METHOD(handle_cache.view.class, "onKeyDown", "(ILandroid/view/KeyEvent;)Z");
|
||||
|
||||
handle_cache.view_group.class = _REF((*env)->FindClass(env, "android/view/ViewGroup"));
|
||||
handle_cache.view_group.dispatchTouchEvent = _METHOD(handle_cache.view_group.class, "dispatchTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||
|
||||
handle_cache.asset_manager.class = _REF((*env)->FindClass(env, "android/content/res/AssetManager"));
|
||||
handle_cache.asset_manager.extractFromAPK = _STATIC_METHOD(handle_cache.asset_manager.class, "extractFromAPK", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ struct handle_cache {
|
|||
jmethodID getScrollY;
|
||||
jmethodID performClick;
|
||||
jmethodID onTouchEvent;
|
||||
jmethodID onTouchEventInternal;
|
||||
jmethodID dispatchTouchEvent;
|
||||
jmethodID onInterceptTouchEvent;
|
||||
jmethodID layoutInternal;
|
||||
|
@ -88,6 +89,10 @@ struct handle_cache {
|
|||
jmethodID dispatchKeyEvent;
|
||||
jmethodID onKeyDown;
|
||||
} view;
|
||||
struct {
|
||||
jclass class;
|
||||
jmethodID dispatchTouchEvent;
|
||||
} view_group;
|
||||
struct {
|
||||
jclass class;
|
||||
jmethodID extractFromAPK;
|
||||
|
|
|
@ -46,11 +46,40 @@ static WrapperWidget *cancel_triggerer = NULL;
|
|||
|
||||
static struct pointer pointers[MAX_POINTERS] = {};
|
||||
|
||||
bool view_dispatch_motionevent(JNIEnv *env, WrapperWidget *wrapper, GtkPropagationPhase phase, jobject motion_event, GdkEvent *event) {
|
||||
int ret;
|
||||
|
||||
jobject this = wrapper->jobj;
|
||||
|
||||
if (wrapper->custom_dispatch_touch) {
|
||||
ret = (*env)->CallBooleanMethod(env, this, handle_cache.view.dispatchTouchEvent, motion_event);
|
||||
} else if (phase == GTK_PHASE_CAPTURE && !wrapper->intercepting_touch) {
|
||||
wrapper->intercepting_touch = (*env)->CallBooleanMethod(env, this, handle_cache.view.onInterceptTouchEvent, motion_event);
|
||||
if (wrapper->intercepting_touch) {
|
||||
if(event) {
|
||||
// store the event that was canceled and let it propagate to the child widgets
|
||||
canceled_event = event;
|
||||
cancel_triggerer = wrapper;
|
||||
} else {
|
||||
/* this function is also called to synthesize an event, in which case there is no GdkEvent so not sure what to do */
|
||||
fprintf(stderr, "view_dispatch_motionevent: onInterceptTouchEvent returned true but this is a synthesized event, please investigate\n");
|
||||
}
|
||||
}
|
||||
ret = false;
|
||||
} else {
|
||||
ret = (*env)->CallBooleanMethod(env, this, handle_cache.view.onTouchEventInternal, motion_event);
|
||||
}
|
||||
|
||||
if((*env)->ExceptionCheck(env))
|
||||
(*env)->ExceptionDescribe(env);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool call_ontouch_callback(WrapperWidget *wrapper, int action, struct pointer pointers[MAX_POINTERS], GPtrArray *pointer_indices, GtkPropagationPhase phase, guint32 timestamp, GdkEvent *event)
|
||||
{
|
||||
bool ret;
|
||||
JNIEnv *env = get_jni_env();
|
||||
jobject this = wrapper->jobj;
|
||||
|
||||
int num_pointers = pointer_indices->len;
|
||||
jintArray ids = (*env)->NewIntArray(env, num_pointers);
|
||||
|
@ -62,24 +91,9 @@ static bool call_ontouch_callback(WrapperWidget *wrapper, int action, struct poi
|
|||
(*env)->SetFloatArrayRegion(env, coords, 4 * i, 4, &pointer->coord_x);
|
||||
}
|
||||
|
||||
jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_TOUCHSCREEN, action, (long)timestamp, ids, coords);
|
||||
jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_TOUCHSCREEN, action, timestamp, ids, coords);
|
||||
|
||||
if (wrapper->custom_dispatch_touch) {
|
||||
ret = (*env)->CallBooleanMethod(env, this, handle_cache.view.dispatchTouchEvent, motion_event);
|
||||
} else if (phase == GTK_PHASE_CAPTURE && !wrapper->intercepting_touch) {
|
||||
wrapper->intercepting_touch = (*env)->CallBooleanMethod(env, this, handle_cache.view.onInterceptTouchEvent, motion_event);
|
||||
if (wrapper->intercepting_touch) {
|
||||
// store the event that was canceled and let it propagate to the child widgets
|
||||
canceled_event = event;
|
||||
cancel_triggerer = wrapper;
|
||||
}
|
||||
ret = false;
|
||||
} else {
|
||||
ret = (*env)->CallBooleanMethod(env, this, handle_cache.view.onTouchEvent, motion_event);
|
||||
}
|
||||
|
||||
if((*env)->ExceptionCheck(env))
|
||||
(*env)->ExceptionDescribe(env);
|
||||
ret = view_dispatch_motionevent(env, wrapper, phase, motion_event, event);
|
||||
|
||||
(*env)->DeleteLocalRef(env, motion_event);
|
||||
|
||||
|
|
|
@ -63,3 +63,103 @@ JNIEXPORT void JNICALL Java_android_view_ViewGroup_native_1drawChild(JNIEnv *env
|
|||
gtk_widget_queue_draw(child); // FIXME: why didn't compose UI invalidate the child?
|
||||
gtk_widget_snapshot_child(widget, child, snapshot);
|
||||
}
|
||||
|
||||
/* FIXME: put this in a header */
|
||||
G_DECLARE_FINAL_TYPE(JavaWidget, java_widget, JAVA, WIDGET, GtkWidget)
|
||||
bool view_dispatch_motionevent(JNIEnv *env, WrapperWidget *wrapper, GtkPropagationPhase phase, jobject motion_event, GdkEvent *event);
|
||||
|
||||
static bool dispatch_motionevent_if_JavaWidget(GtkWidget *widget, GtkPropagationPhase phase, jobject motion_event)
|
||||
{
|
||||
if(!JAVA_IS_WIDGET(widget))
|
||||
return false;
|
||||
|
||||
return view_dispatch_motionevent(get_jni_env(), WRAPPER_WIDGET(gtk_widget_get_parent(widget)), phase, motion_event, NULL);
|
||||
}
|
||||
|
||||
/* used by atl_propagate_synthetic_motionevent */
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GtkWidget *
|
||||
#define GDK_ARRAY_TYPE_NAME GtkWidgetStack
|
||||
#define GDK_ARRAY_NAME gtk_widget_stack
|
||||
#define GDK_ARRAY_FREE_FUNC g_object_unref
|
||||
#define GDK_ARRAY_PREALLOC 16
|
||||
#include "gdkarrayimpl.c"
|
||||
|
||||
/* based on gtk_propagate_event_internal © GTK Team */
|
||||
bool atl_propagate_synthetic_motionevent(GtkWidget *widget, jobject motionevent, GtkWidget *toplevel)
|
||||
{
|
||||
int handled_event = false;
|
||||
GtkWidgetStack widget_array;
|
||||
int i;
|
||||
|
||||
/* First, propagate event down */
|
||||
gtk_widget_stack_init(&widget_array);
|
||||
gtk_widget_stack_append(&widget_array, g_object_ref(widget));
|
||||
|
||||
for (;;) {
|
||||
widget = gtk_widget_get_parent(widget);
|
||||
if (!widget)
|
||||
break;
|
||||
|
||||
if (widget == toplevel)
|
||||
break;
|
||||
|
||||
gtk_widget_stack_append(&widget_array, g_object_ref(widget));
|
||||
}
|
||||
|
||||
i = gtk_widget_stack_get_size(&widget_array) - 1;
|
||||
for (;;) {
|
||||
widget = gtk_widget_stack_get(&widget_array, i);
|
||||
|
||||
if (!gtk_widget_is_sensitive(widget)) {
|
||||
handled_event = true;
|
||||
} else if (gtk_widget_get_realized(widget))
|
||||
handled_event = dispatch_motionevent_if_JavaWidget(widget, GTK_PHASE_CAPTURE, motionevent);
|
||||
|
||||
handled_event |= !gtk_widget_get_realized(widget);
|
||||
|
||||
if (handled_event)
|
||||
break;
|
||||
|
||||
if (i == 0)
|
||||
break;
|
||||
|
||||
i--;
|
||||
}
|
||||
|
||||
/* If not yet handled, also propagate back up */
|
||||
if (!handled_event) {
|
||||
/* Propagate event up the widget tree so that
|
||||
* parents can see the button and motion
|
||||
* events of the children.
|
||||
*/
|
||||
for (i = 0; i < gtk_widget_stack_get_size(&widget_array); i++) {
|
||||
widget = gtk_widget_stack_get(&widget_array, i);
|
||||
|
||||
/* Scroll events are special cased here because it
|
||||
* feels wrong when scrolling a GtkViewport, say,
|
||||
* to have children of the viewport eat the scroll
|
||||
* event
|
||||
*/
|
||||
if (!gtk_widget_is_sensitive(widget))
|
||||
handled_event = true;
|
||||
else if (gtk_widget_get_realized(widget))
|
||||
handled_event = dispatch_motionevent_if_JavaWidget(widget, GTK_PHASE_BUBBLE, motionevent);
|
||||
|
||||
handled_event |= !gtk_widget_get_realized(widget);
|
||||
|
||||
if (handled_event)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_stack_clear(&widget_array);
|
||||
return handled_event;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_android_view_ViewGroup_native_1dispatchTouchEvent(JNIEnv *env, jobject this, jlong widget_ptr, jobject motion_event, jdouble x, jdouble y)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr));
|
||||
GtkWidget *picked_child = gtk_widget_pick(widget, x, y, GTK_PICK_DEFAULT);
|
||||
|
||||
return atl_propagate_synthetic_motionevent(picked_child, motion_event, widget);
|
||||
}
|
||||
|
|
326
src/api-impl-jni/views/gdkarrayimpl.c
Normal file
326
src/api-impl-jni/views/gdkarrayimpl.c
Normal file
|
@ -0,0 +1,326 @@
|
|||
/* lifted from Gtk for gtk_propagate_event_internal derived function */
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef GDK_ARRAY_TYPE_NAME
|
||||
#define GDK_ARRAY_TYPE_NAME GdkArray
|
||||
#endif
|
||||
|
||||
#ifndef GDK_ARRAY_NAME
|
||||
#define GDK_ARRAY_NAME gdk_array
|
||||
#endif
|
||||
|
||||
#ifndef GDK_ARRAY_ELEMENT_TYPE
|
||||
#define GDK_ARRAY_ELEMENT_TYPE gpointer
|
||||
#endif
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
#if GDK_ARRAY_PREALLOC == 0
|
||||
#undef GDK_ARRAY_PREALLOC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
|
||||
#define GDK_ARRAY_MAX_SIZE (G_MAXSIZE / sizeof(_T_) - 1)
|
||||
#else
|
||||
#define GDK_ARRAY_REAL_SIZE(_size) (_size)
|
||||
#define GDK_ARRAY_MAX_SIZE (G_MAXSIZE / sizeof(_T_))
|
||||
#endif
|
||||
|
||||
/* make this readable */
|
||||
#define _T_ GDK_ARRAY_ELEMENT_TYPE
|
||||
#define GdkArray GDK_ARRAY_TYPE_NAME
|
||||
#define gdk_array_paste_more(GDK_ARRAY_NAME, func_name) GDK_ARRAY_NAME##_##func_name
|
||||
#define gdk_array_paste(GDK_ARRAY_NAME, func_name) gdk_array_paste_more(GDK_ARRAY_NAME, func_name)
|
||||
#define gdk_array(func_name) gdk_array_paste(GDK_ARRAY_NAME, func_name)
|
||||
|
||||
typedef struct GdkArray GdkArray;
|
||||
|
||||
struct GdkArray {
|
||||
_T_ *start;
|
||||
_T_ *end;
|
||||
_T_ *end_allocation;
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
_T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* no G_GNUC_UNUSED here, if you don't use an array type, remove it. */
|
||||
static inline void
|
||||
gdk_array(init)(GdkArray *self)
|
||||
{
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
self->start = self->preallocated;
|
||||
self->end = self->start;
|
||||
self->end_allocation = self->start + GDK_ARRAY_PREALLOC;
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
*self->start = *(_T_[1]){0};
|
||||
#endif
|
||||
#else
|
||||
self->start = NULL;
|
||||
self->end = NULL;
|
||||
self->end_allocation = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gsize
|
||||
gdk_array(get_capacity)(const GdkArray *self)
|
||||
{
|
||||
return self->end_allocation - self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gsize
|
||||
gdk_array(get_size)(const GdkArray *self)
|
||||
{
|
||||
return self->end - self->start;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_array(free_elements)(_T_ *start,
|
||||
_T_ *end)
|
||||
{
|
||||
#ifdef GDK_ARRAY_FREE_FUNC
|
||||
_T_ *e;
|
||||
for (e = start; e < end; e++)
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
GDK_ARRAY_FREE_FUNC(e);
|
||||
#else
|
||||
GDK_ARRAY_FREE_FUNC(*e);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* no G_GNUC_UNUSED here */
|
||||
static inline void
|
||||
gdk_array(clear)(GdkArray *self)
|
||||
{
|
||||
gdk_array(free_elements)(self->start, self->end);
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
if (self->start != self->preallocated)
|
||||
#endif
|
||||
g_free(self->start);
|
||||
gdk_array(init)(self);
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_array_steal:
|
||||
* @self: the array
|
||||
*
|
||||
* Steals all data in the array and clears the array.
|
||||
*
|
||||
* If you need to know the size of the data, you should query it
|
||||
* beforehand.
|
||||
*
|
||||
* Returns: The array's data
|
||||
**/
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gdk_array(steal)(GdkArray *self)
|
||||
{
|
||||
_T_ *result;
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
if (self->start == self->preallocated) {
|
||||
gsize size = GDK_ARRAY_REAL_SIZE(gdk_array(get_size)(self));
|
||||
result = g_new(_T_, size);
|
||||
memcpy(result, self->preallocated, sizeof(_T_) * size);
|
||||
} else
|
||||
#endif
|
||||
result = self->start;
|
||||
|
||||
gdk_array(init)(self);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gdk_array(get_data)(const GdkArray *self)
|
||||
{
|
||||
return self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gdk_array(index)(const GdkArray *self,
|
||||
gsize pos)
|
||||
{
|
||||
return self->start + pos;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gboolean
|
||||
gdk_array(is_empty)(const GdkArray *self)
|
||||
{
|
||||
return self->end == self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline void
|
||||
gdk_array(reserve)(GdkArray *self,
|
||||
gsize n)
|
||||
{
|
||||
gsize new_capacity, size, capacity;
|
||||
|
||||
if (G_UNLIKELY(n > GDK_ARRAY_MAX_SIZE))
|
||||
g_error("requesting array size of %zu, but maximum size is %zu", n, GDK_ARRAY_MAX_SIZE);
|
||||
|
||||
capacity = gdk_array(get_capacity)(self);
|
||||
if (n <= capacity)
|
||||
return;
|
||||
|
||||
size = gdk_array(get_size)(self);
|
||||
/* capacity * 2 can overflow, that's why we MAX() */
|
||||
new_capacity = MAX(GDK_ARRAY_REAL_SIZE(n), capacity * 2);
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
if (self->start == self->preallocated) {
|
||||
self->start = g_new(_T_, new_capacity);
|
||||
memcpy(self->start, self->preallocated, sizeof(_T_) * GDK_ARRAY_REAL_SIZE(size));
|
||||
} else
|
||||
#endif
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
if (self->start == NULL) {
|
||||
self->start = g_new(_T_, new_capacity);
|
||||
*self->start = *(_T_[1]){0};
|
||||
} else
|
||||
#endif
|
||||
self->start = g_renew(_T_, self->start, new_capacity);
|
||||
|
||||
self->end = self->start + size;
|
||||
self->end_allocation = self->start + new_capacity;
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
self->end_allocation--;
|
||||
#endif
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline void
|
||||
gdk_array(splice)(GdkArray *self,
|
||||
gsize pos,
|
||||
gsize removed,
|
||||
gboolean stolen,
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
const _T_ *additions,
|
||||
#else
|
||||
_T_ *additions,
|
||||
#endif
|
||||
gsize added)
|
||||
{
|
||||
gsize size;
|
||||
gsize remaining;
|
||||
|
||||
size = gdk_array(get_size)(self);
|
||||
g_assert(pos + removed <= size);
|
||||
remaining = size - pos - removed;
|
||||
|
||||
if (!stolen)
|
||||
gdk_array(free_elements)(gdk_array(index)(self, pos),
|
||||
gdk_array(index)(self, pos + removed));
|
||||
|
||||
gdk_array(reserve)(self, size - removed + added);
|
||||
|
||||
if (GDK_ARRAY_REAL_SIZE(remaining) && removed != added)
|
||||
memmove(gdk_array(index)(self, pos + added),
|
||||
gdk_array(index)(self, pos + removed),
|
||||
GDK_ARRAY_REAL_SIZE(remaining) * sizeof(_T_));
|
||||
|
||||
if (added) {
|
||||
if (additions)
|
||||
memcpy(gdk_array(index)(self, pos),
|
||||
additions,
|
||||
added * sizeof(_T_));
|
||||
#ifndef GDK_ARRAY_NO_MEMSET
|
||||
else
|
||||
memset(gdk_array(index)(self, pos), 0, added * sizeof(_T_));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* might overflow, but does the right thing */
|
||||
self->end += added - removed;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gdk_array(set_size)(GdkArray *self,
|
||||
gsize new_size)
|
||||
{
|
||||
gsize old_size = gdk_array(get_size)(self);
|
||||
if (new_size > old_size)
|
||||
gdk_array(splice)(self, old_size, 0, FALSE, NULL, new_size - old_size);
|
||||
else
|
||||
gdk_array(splice)(self, new_size, old_size - new_size, FALSE, NULL, 0);
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gdk_array(append)(GdkArray *self,
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
_T_ *value)
|
||||
#else
|
||||
_T_ value)
|
||||
#endif
|
||||
{
|
||||
gdk_array(splice)(self,
|
||||
gdk_array(get_size)(self),
|
||||
0,
|
||||
FALSE,
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
value,
|
||||
#else
|
||||
&value,
|
||||
#endif
|
||||
1);
|
||||
}
|
||||
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
G_GNUC_UNUSED static _T_ *
|
||||
gdk_array(get)(const GdkArray *self,
|
||||
gsize pos)
|
||||
{
|
||||
return gdk_array(index)(self, pos);
|
||||
}
|
||||
#else
|
||||
G_GNUC_UNUSED static _T_
|
||||
gdk_array(get)(const GdkArray *self,
|
||||
gsize pos)
|
||||
{
|
||||
return *gdk_array(index)(self, pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GDK_ARRAY_NO_UNDEF
|
||||
|
||||
#undef _T_
|
||||
#undef GdkArray
|
||||
#undef gdk_array_paste_more
|
||||
#undef gdk_array_paste
|
||||
#undef gdk_array
|
||||
#undef GDK_ARRAY_REAL_SIZE
|
||||
#undef GDK_ARRAY_MAX_SIZE
|
||||
|
||||
#undef GDK_ARRAY_BY_VALUE
|
||||
#undef GDK_ARRAY_ELEMENT_TYPE
|
||||
#undef GDK_ARRAY_FREE_FUNC
|
||||
#undef GDK_ARRAY_NAME
|
||||
#undef GDK_ARRAY_NULL_TERMINATED
|
||||
#undef GDK_ARRAY_PREALLOC
|
||||
#undef GDK_ARRAY_TYPE_NAME
|
||||
#undef GDK_ARRAY_NO_MEMSET
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
|
@ -23,7 +23,7 @@ static void wrapper_widget_set_property (GObject *object, guint property_id, con
|
|||
}
|
||||
}
|
||||
|
||||
static void wrapper_widget_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
static void wrapper_widget_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
WrapperWidget *self = WRAPPER_WIDGET(object);
|
||||
|
||||
|
@ -91,7 +91,7 @@ static void wrapper_widget_get_property (GObject *object, guint property_id, GVa
|
|||
}
|
||||
}
|
||||
|
||||
static void wrapper_widget_init (WrapperWidget *wrapper_widget)
|
||||
static void wrapper_widget_init(WrapperWidget *wrapper_widget)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
|
|||
|
||||
jmethodID ontouchevent_method = _METHOD(_CLASS(jobj), "onTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||
jmethodID dispatchtouchevent_method = _METHOD(_CLASS(jobj), "dispatchTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||
wrapper->custom_dispatch_touch = dispatchtouchevent_method != handle_cache.view.dispatchTouchEvent;
|
||||
wrapper->custom_dispatch_touch = (dispatchtouchevent_method != handle_cache.view.dispatchTouchEvent && dispatchtouchevent_method != handle_cache.view_group.dispatchTouchEvent);
|
||||
if (ontouchevent_method != handle_cache.view.onTouchEvent || wrapper->custom_dispatch_touch) {
|
||||
_setOnTouchListener(env, jobj, GTK_WIDGET(wrapper));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ JNIEXPORT jlong JNICALL Java_android_widget_PopupWindow_native_1constructor(JNIE
|
|||
{
|
||||
GtkWidget *popover = gtk_popover_new();
|
||||
gtk_widget_set_name(popover, "PopupWindow");
|
||||
/* autohiding works by the widget grabbing events, which is not something apps expect */
|
||||
gtk_popover_set_autohide(GTK_POPOVER(popover), false);
|
||||
return _INTPTR(popover);
|
||||
}
|
||||
|
||||
|
@ -20,32 +22,76 @@ JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setContentView(JN
|
|||
gtk_popover_set_child(GTK_POPOVER(_PTR(popover_ptr)), GTK_WIDGET(content));
|
||||
}
|
||||
|
||||
static inline void set_offset(GtkPopover *popover, GtkWidget *anchor, int x, int y)
|
||||
{
|
||||
/* FIXME: assumes GTK_POS_BOTTOM */
|
||||
gtk_popover_set_offset(popover, x - gtk_widget_get_width(anchor) / 2, y - gtk_widget_get_height(anchor));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1showAsDropDown(JNIEnv *env, jobject this, jlong popover_ptr, jlong anchor_ptr, jint x, jint y, jint gravity)
|
||||
{
|
||||
GtkPopover *popover = GTK_POPOVER(_PTR(popover_ptr));
|
||||
WrapperWidget *anchor = WRAPPER_WIDGET(gtk_widget_get_parent(GTK_WIDGET(_PTR(anchor_ptr))));
|
||||
|
||||
gtk_widget_insert_before(GTK_WIDGET(popover), GTK_WIDGET(anchor), NULL);
|
||||
set_offset(popover, GTK_WIDGET(anchor), x, y);
|
||||
gtk_popover_present(GTK_POPOVER(popover));
|
||||
gtk_popover_popup(popover);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_setWidth(JNIEnv *env, jobject this, jint width)
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setWidth(JNIEnv *env, jobject this, jlong popover_ptr, jint width)
|
||||
{
|
||||
int height;
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "popover")));
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(popover_ptr));
|
||||
gtk_widget_get_size_request(popover, NULL, &height);
|
||||
gtk_widget_set_size_request(popover, width, height);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_setHeight(JNIEnv *env, jobject this, jint height)
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setHeight(JNIEnv *env, jobject this, jlong popover_ptr, jint height)
|
||||
{
|
||||
int width;
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "popover")));
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(popover_ptr));
|
||||
gtk_widget_get_size_request(popover, &width, NULL);
|
||||
gtk_widget_set_size_request(popover, width, height);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_android_widget_PopupWindow_native_1getWidth(JNIEnv *env, jobject this, jlong popover_ptr)
|
||||
{
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(popover_ptr));
|
||||
GtkRequisition natural_size;
|
||||
gtk_widget_get_preferred_size(popover, &natural_size, NULL);
|
||||
return natural_size.width;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_android_widget_PopupWindow_native_1getHeight(JNIEnv *env, jobject this, jlong popover_ptr)
|
||||
{
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(popover_ptr));
|
||||
GtkRequisition natural_size;
|
||||
gtk_widget_get_preferred_size(popover, &natural_size, NULL);
|
||||
return natural_size.height;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setTouchable(JNIEnv *env, jobject this, jlong popover_ptr, jboolean touchable)
|
||||
{
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(popover_ptr));
|
||||
gtk_widget_set_sensitive(popover, touchable);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_android_widget_PopupWindow_native_1isTouchable(JNIEnv *env, jobject this, jlong popover_ptr)
|
||||
{
|
||||
GtkWidget *popover = GTK_WIDGET(_PTR(popover_ptr));
|
||||
return gtk_widget_is_sensitive(popover);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1setTouchModal(JNIEnv *env, jobject this, jlong popover_ptr, jboolean touch_modal)
|
||||
{
|
||||
GtkPopover *popover = GTK_POPOVER(_PTR(popover_ptr));
|
||||
/* FIXME: we should only add grab (not autohide), however we need to remove it again in umap;
|
||||
* GtkPopover is not final, so we should subclass it and check whether it's modal in map/unmap
|
||||
* to add/remove grab, which is the desired part of what GtkPopover does with autohide enabled */
|
||||
gtk_popover_set_autohide(popover, touch_modal);
|
||||
}
|
||||
|
||||
static void on_closed_cb(GtkPopover *popover, jobject listener)
|
||||
{
|
||||
JNIEnv *env = get_jni_env();
|
||||
|
@ -74,6 +120,7 @@ JNIEXPORT void JNICALL Java_android_widget_PopupWindow_native_1update(JNIEnv *en
|
|||
GtkPopover *popover = GTK_POPOVER(_PTR(popover_ptr));
|
||||
WrapperWidget *anchor = WRAPPER_WIDGET(gtk_widget_get_parent(GTK_WIDGET(_PTR(anchor_ptr))));
|
||||
gtk_widget_set_size_request(GTK_WIDGET(popover), width, height);
|
||||
set_offset(popover, GTK_WIDGET(anchor), x, y);
|
||||
gtk_widget_insert_before(GTK_WIDGET(popover), GTK_WIDGET(anchor), NULL);
|
||||
gtk_popover_present(GTK_POPOVER(popover));
|
||||
gtk_popover_popup(popover);
|
||||
|
|
File diff suppressed because it is too large
Load diff
42
src/api-impl/android/animation/FloatEvaluator.java
Normal file
42
src/api-impl/android/animation/FloatEvaluator.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.animation;
|
||||
|
||||
/**
|
||||
* This evaluator can be used to perform type interpolation between <code>float</code> values.
|
||||
*/
|
||||
public class FloatEvaluator /*implements TypeEvaluator<Number>*/ {
|
||||
|
||||
/**
|
||||
* This function returns the result of linearly interpolating the start and end values, with
|
||||
* <code>fraction</code> representing the proportion between the start and end values. The
|
||||
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
|
||||
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
|
||||
* and <code>t</code> is <code>fraction</code>.
|
||||
*
|
||||
* @param fraction The fraction from the starting to the ending values
|
||||
* @param startValue The start value; should be of type <code>float</code> or
|
||||
* <code>Float</code>
|
||||
* @param endValue The end value; should be of type <code>float</code> or <code>Float</code>
|
||||
* @return A linear interpolation between the start and end values, given the
|
||||
* <code>fraction</code> parameter.
|
||||
*/
|
||||
public Float evaluate(float fraction, Number startValue, Number endValue) {
|
||||
float startFloat = startValue.floatValue();
|
||||
return startFloat + fraction * (endValue.floatValue() - startFloat);
|
||||
}
|
||||
}
|
|
@ -8,4 +8,8 @@ public class KeyguardManager {
|
|||
public boolean isKeyguardLocked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isKeyguardSecure() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
9
src/api-impl/android/app/backup/BackupAgent.java
Normal file
9
src/api-impl/android/app/backup/BackupAgent.java
Normal file
|
@ -0,0 +1,9 @@
|
|||
package android.app.backup;
|
||||
|
||||
import android.content.ContextWrapper;
|
||||
|
||||
public abstract class BackupAgent extends ContextWrapper {
|
||||
public BackupAgent() {
|
||||
super(null);
|
||||
}
|
||||
}
|
5
src/api-impl/android/app/backup/BackupAgentHelper.java
Normal file
5
src/api-impl/android/app/backup/BackupAgentHelper.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package android.app.backup;
|
||||
|
||||
public class BackupAgentHelper extends BackupAgent {
|
||||
|
||||
}
|
8
src/api-impl/android/app/backup/BackupManager.java
Normal file
8
src/api-impl/android/app/backup/BackupManager.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package android.app.backup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public class BackupManager {
|
||||
public BackupManager(Context context) {
|
||||
}
|
||||
}
|
|
@ -10,15 +10,7 @@ public class JobInfo {
|
|||
public static final class Builder {
|
||||
public Builder(int jobId, ComponentName jobService) {}
|
||||
|
||||
public Builder setMinimumLatency(long minLatencyMillis) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRequiredNetworkType(int networkType) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setOverrideDeadline(long a) {
|
||||
public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -26,15 +18,15 @@ public class JobInfo {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setRequiresCharging(boolean requiresCharging) {
|
||||
public Builder setMinimumLatency(long minLatencyMillis) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRequiresDeviceIdle(boolean requiresDeviceIdle) {
|
||||
public Builder setOverrideDeadline(long a) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) {
|
||||
public Builder setPeriodic(long dummy) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -42,6 +34,18 @@ public class JobInfo {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder setRequiredNetworkType(int networkType) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRequiresCharging(boolean requires_charging) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRequiresDeviceIdle(boolean requires_device_idle) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public JobInfo build() {
|
||||
return new JobInfo();
|
||||
}
|
||||
|
|
|
@ -21,4 +21,7 @@ public class JobScheduler {
|
|||
public int schedule(JobInfo job) {
|
||||
return 1; //RESULT_SUCCESS
|
||||
}
|
||||
|
||||
public void cancel(int dummy) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,14 @@ public abstract class ContentProvider {
|
|||
|
||||
static void createContentProviders() {
|
||||
for (PackageParser.Provider provider_parsed : Context.pkg.providers) {
|
||||
String process_name = provider_parsed.info.processName;
|
||||
if(process_name != null && process_name.contains(":")) {
|
||||
/* NOTE: even if it doesn't contain `:`, if it's not null we probably
|
||||
* need to check what it's requesting; `:` means it wants us to spawn
|
||||
* a new process, which we currently don't support */
|
||||
System.out.println("not creating provider " + provider_parsed.className + ", it wants to be started in a new process (" + process_name + ")");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String providerName = provider_parsed.className;
|
||||
System.out.println("creating " + providerName);
|
||||
|
|
|
@ -238,6 +238,8 @@ public class Context extends Object {
|
|||
return new JobScheduler();
|
||||
case "appops":
|
||||
return new AppOpsManager();
|
||||
case "user":
|
||||
return new UserManager();
|
||||
default:
|
||||
Slog.e(TAG, "!!!!!!! getSystemService: case >" + name + "< is not implemented yet");
|
||||
return null;
|
||||
|
@ -717,4 +719,9 @@ public class Context extends Object {
|
|||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
public Context createDeviceProtectedStorageContext() {
|
||||
/* FIXME: should be a different context, and return different storage locations */
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,10 @@ public class IntentFilter {
|
|||
|
||||
public void addDataPath(String path, int type) {}
|
||||
|
||||
public final void addDataSchemeSpecificPart(String ssp, int type) {
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
public boolean hasDataScheme(String dataScheme) {
|
||||
return dataSchemes.contains(dataScheme);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package android.content.pm;
|
|||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -1834,6 +1835,14 @@ public class PackageManager {
|
|||
case "android.permission.READ_EXTERNAL_STORAGE":
|
||||
case "com.google.android.c2dm.permission.SEND":
|
||||
return PERMISSION_GRANTED;
|
||||
// only tell the app that it can access location if it *actually* can
|
||||
// (until we find apps that refuse to launch without being lied to anyway)
|
||||
case "android.permission.ACCESS_FINE_LOCATION":
|
||||
case "android.permission.ACCESS_COARSE_LOCATION":
|
||||
if(System.getenv("ATL_UGLY_ENABLE_LOCATION") != null)
|
||||
return PERMISSION_GRANTED;
|
||||
else
|
||||
return PERMISSION_DENIED;
|
||||
default:
|
||||
System.out.println("PackageManager.checkPermission: >" + permName + "< not handled\n");
|
||||
return PERMISSION_DENIED;
|
||||
|
@ -2142,7 +2151,34 @@ public class PackageManager {
|
|||
* @see #GET_RESOLVED_FILTER
|
||||
*/
|
||||
public ResolveInfo resolveActivity(Intent intent, int flags) {
|
||||
return new ResolveInfo();
|
||||
ResolveInfo info = null;
|
||||
ActivityInfo activity_info = null;
|
||||
|
||||
if (intent.getComponent() != null) {
|
||||
for (PackageParser.Activity activity: Context.pkg.activities) {
|
||||
if (intent.getComponent().getClassName() == activity.className)
|
||||
activity_info = activity.info;
|
||||
}
|
||||
} else {
|
||||
for (PackageParser.Activity activity: Context.pkg.activities) {
|
||||
for (PackageParser.IntentInfo intentInfo: activity.intents) {
|
||||
if (intentInfo.matchAction(intent.getAction())) {
|
||||
activity_info = activity.info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (activity_info == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
info = new ResolveInfo();
|
||||
info.activityInfo.exported = true;
|
||||
info.activityInfo = activity_info;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2200,9 +2236,12 @@ public class PackageManager {
|
|||
*/
|
||||
public List<ResolveInfo> queryIntentActivities(Intent intent,
|
||||
int flags) {
|
||||
ResolveInfo info = new ResolveInfo();
|
||||
info.activityInfo.exported = true;
|
||||
return Arrays.asList(info);
|
||||
/* FIXME - we may need to return more than one */
|
||||
ResolveInfo info = resolveActivity(intent, flags);
|
||||
if (info != null)
|
||||
return Arrays.asList(info);
|
||||
else
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1042,7 +1042,7 @@ public final class Configuration implements Comparable<Configuration> {
|
|||
public void setToDefaults() {
|
||||
fontScale = 1;
|
||||
mcc = mnc = 0;
|
||||
locale = null;
|
||||
locale = new Locale("en", "US");
|
||||
userSetLocale = false;
|
||||
touchscreen = TOUCHSCREEN_UNDEFINED;
|
||||
keyboard = KEYBOARD_UNDEFINED;
|
||||
|
|
|
@ -137,7 +137,7 @@ final class XmlBlock {
|
|||
}
|
||||
public String getText() {
|
||||
int id = nativeGetText(mParseState);
|
||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
||||
return id >= 0 ? (String)getPooledString(id) : null;
|
||||
}
|
||||
public int getLineNumber() {
|
||||
return nativeGetLineNumber(mParseState);
|
||||
|
@ -165,7 +165,7 @@ final class XmlBlock {
|
|||
}
|
||||
public String getNamespace() {
|
||||
int id = nativeGetNamespace(mParseState);
|
||||
return id >= 0 ? mStrings.get(id).toString() : "";
|
||||
return id >= 0 ? (String)getPooledString(id) : "";
|
||||
}
|
||||
public String getName() {
|
||||
return nativeGetName(mParseState);
|
||||
|
@ -175,7 +175,7 @@ final class XmlBlock {
|
|||
if (DEBUG)
|
||||
System.out.println("getAttributeNamespace of " + index + " = " + id);
|
||||
if (id >= 0)
|
||||
return mStrings.get(id).toString();
|
||||
return (String)getPooledString(id);
|
||||
else if (id == -1)
|
||||
return "";
|
||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||
|
@ -185,7 +185,7 @@ final class XmlBlock {
|
|||
if (DEBUG)
|
||||
System.out.println("getAttributeName of " + index + " = " + id);
|
||||
if (id >= 0)
|
||||
return mStrings.get(id).toString();
|
||||
return (String)getPooledString(id);
|
||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||
}
|
||||
public String getAttributePrefix(int index) {
|
||||
|
@ -417,7 +417,7 @@ final class XmlBlock {
|
|||
|
||||
public String getIdAttribute() {
|
||||
int id = nativeGetIdAttribute(mParseState);
|
||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
||||
return id >= 0 ? (String)getPooledString(id) : null;
|
||||
}
|
||||
public String getClassAttribute() {
|
||||
return nativeGetClassAttribute(mParseState);
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package android.graphics;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
|
||||
public class Canvas {
|
||||
public static final int HAS_ALPHA_LAYER_SAVE_FLAG = (1 << 2);
|
||||
|
||||
|
@ -136,6 +139,7 @@ public class Canvas {
|
|||
* @param paint The paint used for the text (e.g. color, size, style)
|
||||
*/
|
||||
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
|
||||
drawText(text.toString(), start, end, x, y, paint);
|
||||
/*if (text instanceof String || text instanceof SpannedString ||
|
||||
text instanceof SpannableString) {
|
||||
native_drawText(mNativeCanvas, text.toString(), start, end, x, y,
|
||||
|
@ -151,6 +155,11 @@ public class Canvas {
|
|||
TemporaryBuffer.recycle(buf);
|
||||
}*/
|
||||
}
|
||||
|
||||
public void drawTextOnPath(String text, Path path, float x_offset, float y_offset, Paint paint) {
|
||||
Log.w("Canvas", "STUB: drawTextOnPath");
|
||||
}
|
||||
|
||||
// ---
|
||||
/**
|
||||
* <p>Draw the specified arc, which will be scaled to fit inside the
|
||||
|
@ -180,6 +189,7 @@ public class Canvas {
|
|||
if (oval == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Log.w("Canvas", "STUB: drawArc");
|
||||
/*native_drawArc(mNativeCanvas, oval, startAngle, sweepAngle,
|
||||
useCenter, paint.mNativePaint);*/
|
||||
}
|
||||
|
@ -308,7 +318,7 @@ public class Canvas {
|
|||
*/
|
||||
public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
|
||||
int width, int height, boolean hasAlpha, Paint paint) {
|
||||
System.out.println("XXXXXXX bitmap(colors, offset, ...)");
|
||||
Log.w("Canvas", "STUB: drawBitmap(colors, offset, ...)");
|
||||
/* // check for valid input
|
||||
if (width < 0) {
|
||||
throw new IllegalArgumentException("width must be >= 0");
|
||||
|
@ -417,7 +427,9 @@ public class Canvas {
|
|||
matrix.reset();
|
||||
}
|
||||
|
||||
public void translate(float dx, float dy) {}
|
||||
public void translate(float dx, float dy) {
|
||||
Log.w("Canvas", "STUB: translate");
|
||||
}
|
||||
|
||||
public void drawCircle(float cx, float cy, float radius, Paint paint) {
|
||||
gsk_canvas.snapshot = bitmap.getSnapshot();
|
||||
|
@ -425,14 +437,18 @@ public class Canvas {
|
|||
}
|
||||
|
||||
public Rect getClipBounds() {
|
||||
return new Rect(0, 0, 10, 10);
|
||||
Rect rect = new Rect();
|
||||
getClipBounds(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
public boolean clipRect(Rect rect, Region.Op op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void concat(Matrix matrix) {}
|
||||
public void concat(Matrix matrix) {
|
||||
Log.w("Canvas", "STUB: concat");
|
||||
}
|
||||
|
||||
public boolean clipPath(Path path, Region.Op op) {
|
||||
return false;
|
||||
|
@ -446,21 +462,29 @@ public class Canvas {
|
|||
return (bitmap == null) ? 0 : bitmap.getHeight();
|
||||
}
|
||||
|
||||
public void drawColor(int dummy) {}
|
||||
public void drawColor(int color) {
|
||||
Log.w("Canvas", "STUB: drawColor("+String.format("0x%08x", color)+")");
|
||||
}
|
||||
|
||||
public void drawARGB(int a, int r, int g, int b) {}
|
||||
public void drawARGB(int a, int r, int g, int b) {
|
||||
Log.w("Canvas", "STUB: drawARGB("+a+", "+r+", "+g+", "+b+")");
|
||||
}
|
||||
|
||||
public int saveLayer(RectF bounds, Paint paint, int flags) {
|
||||
return save();
|
||||
}
|
||||
|
||||
public void drawOval(RectF oval, Paint paint) {}
|
||||
public void drawOval(RectF oval, Paint paint) {
|
||||
Log.w("Canvas", "STUB: drawOval");
|
||||
}
|
||||
|
||||
public boolean clipRect(int left, int top, int right, int bottom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void drawColor(int color, PorterDuff.Mode mode) {}
|
||||
public void drawColor(int color, PorterDuff.Mode mode) {
|
||||
Log.w("Canvas", "STUB: drawColor("+String.format("0x%08x", color)+", "+mode+")");
|
||||
}
|
||||
|
||||
public boolean clipRect(Rect rect) {
|
||||
return false;
|
||||
|
@ -486,12 +510,17 @@ public class Canvas {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean includeCenter, Paint paint) {}
|
||||
public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean includeCenter, Paint paint) {
|
||||
Log.w("Canvas", "STUB: drawArc");
|
||||
}
|
||||
|
||||
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) {}
|
||||
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) {
|
||||
Log.w("Canvas", "STUB: drawRoundRect");
|
||||
}
|
||||
|
||||
public boolean getClipBounds(Rect outRect) {
|
||||
outRect.set(0, 0, 100, 100);
|
||||
/* UGLY HACK */
|
||||
outRect.set(0, 0, Resources.getSystem().getDisplayMetrics().widthPixels, Resources.getSystem().getDisplayMetrics().heightPixels);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,10 @@ public class GskCanvas extends Canvas {
|
|||
|
||||
@Override
|
||||
public void drawText(String text, float x, float y, Paint paint) {
|
||||
if(text == null) {
|
||||
new Exception("drawText: text is null; stack trace:").printStackTrace();
|
||||
return;
|
||||
}
|
||||
native_drawText(snapshot, text, x, y, paint != null ? paint.paint : default_paint.paint);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,4 +16,8 @@ public class PathMeasure {
|
|||
public boolean getSegment(float start, float end, Path dst, boolean forceClosed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getPosTan(float distance, float[] pos, float[] tan) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
package android.graphics;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
// import android.util.Pools.SynchronizedPool;
|
||||
public class Region {
|
||||
private static final int MAX_POOL_SIZE = 10;
|
||||
|
@ -70,7 +73,7 @@ public class Region {
|
|||
* Set the region to the empty region
|
||||
*/
|
||||
public void setEmpty() {
|
||||
nativeSetRect(mNativeRegion, 0, 0, 0, 0);
|
||||
Log.w("graphics/Region", "TODO: nativeSetRect(mNativeRegion, 0, 0, 0, 0);");
|
||||
}
|
||||
/**
|
||||
* Set the region to the specified region.
|
||||
|
@ -230,8 +233,8 @@ public class Region {
|
|||
* true if the result of the op is not empty.
|
||||
*/
|
||||
public boolean op(Rect r, Op op) {
|
||||
return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom,
|
||||
op.nativeInt);
|
||||
Log.w("graphics/Region", "TODO: return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom, op.nativeInt);");
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Perform the specified Op on this region and the specified rect. Return
|
||||
|
|
|
@ -66,22 +66,24 @@ public class DrawableContainer extends Drawable {
|
|||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
state.drawables[curIndex].draw(canvas);
|
||||
if (curIndex != -1)
|
||||
state.drawables[curIndex].draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return state.drawables[curIndex].getIntrinsicHeight();
|
||||
return curIndex != -1 ? state.drawables[curIndex].getIntrinsicHeight() : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return state.drawables[curIndex].getIntrinsicWidth();
|
||||
return curIndex != -1 ? state.drawables[curIndex].getIntrinsicWidth() : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBounds(int left, int top, int right, int bottom) {
|
||||
state.drawables[curIndex].setBounds(left, top, right, bottom);
|
||||
if (curIndex != -1)
|
||||
state.drawables[curIndex].setBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public void setEnterFadeDuration(int duration) {}
|
||||
|
|
388
src/api-impl/android/hardware/GeomagneticField.java
Normal file
388
src/api-impl/android/hardware/GeomagneticField.java
Normal file
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.hardware;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Estimates magnetic field at a given point on
|
||||
* Earth, and in particular, to compute the magnetic declination from true
|
||||
* north.
|
||||
*
|
||||
* <p>This uses the World Magnetic Model produced by the United States National
|
||||
* Geospatial-Intelligence Agency. More details about the model can be found at
|
||||
* <a href="http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml">http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml</a>.
|
||||
* This class currently uses WMM-2020 which is valid until 2025, but should
|
||||
* produce acceptable results for several years after that. Future versions of
|
||||
* Android may use a newer version of the model.
|
||||
*/
|
||||
public class GeomagneticField {
|
||||
// The magnetic field at a given point, in nanoteslas in geodetic
|
||||
// coordinates.
|
||||
private float mX;
|
||||
private float mY;
|
||||
private float mZ;
|
||||
|
||||
// Geocentric coordinates -- set by computeGeocentricCoordinates.
|
||||
private float mGcLatitudeRad;
|
||||
private float mGcLongitudeRad;
|
||||
private float mGcRadiusKm;
|
||||
|
||||
// Constants from WGS84 (the coordinate system used by GPS)
|
||||
static private final float EARTH_SEMI_MAJOR_AXIS_KM = 6378.137f;
|
||||
static private final float EARTH_SEMI_MINOR_AXIS_KM = 6356.7523142f;
|
||||
static private final float EARTH_REFERENCE_RADIUS_KM = 6371.2f;
|
||||
|
||||
// These coefficients and the formulae used below are from:
|
||||
// NOAA Technical Report: The US/UK World Magnetic Model for 2020-2025
|
||||
static private final float[][] G_COEFF = new float[][] {
|
||||
{0.0f},
|
||||
{-29404.5f, -1450.7f},
|
||||
{-2500.0f, 2982.0f, 1676.8f},
|
||||
{1363.9f, -2381.0f, 1236.2f, 525.7f},
|
||||
{903.1f, 809.4f, 86.2f, -309.4f, 47.9f},
|
||||
{-234.4f, 363.1f, 187.8f, -140.7f, -151.2f, 13.7f},
|
||||
{65.9f, 65.6f, 73.0f, -121.5f, -36.2f, 13.5f, -64.7f},
|
||||
{80.6f, -76.8f, -8.3f, 56.5f, 15.8f, 6.4f, -7.2f, 9.8f},
|
||||
{23.6f, 9.8f, -17.5f, -0.4f, -21.1f, 15.3f, 13.7f, -16.5f, -0.3f},
|
||||
{5.0f, 8.2f, 2.9f, -1.4f, -1.1f, -13.3f, 1.1f, 8.9f, -9.3f, -11.9f},
|
||||
{-1.9f, -6.2f, -0.1f, 1.7f, -0.9f, 0.6f, -0.9f, 1.9f, 1.4f, -2.4f, -3.9f},
|
||||
{3.0f, -1.4f, -2.5f, 2.4f, -0.9f, 0.3f, -0.7f, -0.1f, 1.4f, -0.6f, 0.2f, 3.1f},
|
||||
{-2.0f, -0.1f, 0.5f, 1.3f, -1.2f, 0.7f, 0.3f, 0.5f, -0.2f, -0.5f, 0.1f, -1.1f, -0.3f}};
|
||||
|
||||
static private final float[][] H_COEFF = new float[][] {
|
||||
{0.0f},
|
||||
{0.0f, 4652.9f},
|
||||
{0.0f, -2991.6f, -734.8f},
|
||||
{0.0f, -82.2f, 241.8f, -542.9f},
|
||||
{0.0f, 282.0f, -158.4f, 199.8f, -350.1f},
|
||||
{0.0f, 47.7f, 208.4f, -121.3f, 32.2f, 99.1f},
|
||||
{0.0f, -19.1f, 25.0f, 52.7f, -64.4f, 9.0f, 68.1f},
|
||||
{0.0f, -51.4f, -16.8f, 2.3f, 23.5f, -2.2f, -27.2f, -1.9f},
|
||||
{0.0f, 8.4f, -15.3f, 12.8f, -11.8f, 14.9f, 3.6f, -6.9f, 2.8f},
|
||||
{0.0f, -23.3f, 11.1f, 9.8f, -5.1f, -6.2f, 7.8f, 0.4f, -1.5f, 9.7f},
|
||||
{0.0f, 3.4f, -0.2f, 3.5f, 4.8f, -8.6f, -0.1f, -4.2f, -3.4f, -0.1f, -8.8f},
|
||||
{0.0f, 0.0f, 2.6f, -0.5f, -0.4f, 0.6f, -0.2f, -1.7f, -1.6f, -3.0f, -2.0f, -2.6f},
|
||||
{0.0f, -1.2f, 0.5f, 1.3f, -1.8f, 0.1f, 0.7f, -0.1f, 0.6f, 0.2f, -0.9f, 0.0f, 0.5f}};
|
||||
|
||||
static private final float[][] DELTA_G = new float[][] {
|
||||
{0.0f},
|
||||
{6.7f, 7.7f},
|
||||
{-11.5f, -7.1f, -2.2f},
|
||||
{2.8f, -6.2f, 3.4f, -12.2f},
|
||||
{-1.1f, -1.6f, -6.0f, 5.4f, -5.5f},
|
||||
{-0.3f, 0.6f, -0.7f, 0.1f, 1.2f, 1.0f},
|
||||
{-0.6f, -0.4f, 0.5f, 1.4f, -1.4f, 0.0f, 0.8f},
|
||||
{-0.1f, -0.3f, -0.1f, 0.7f, 0.2f, -0.5f, -0.8f, 1.0f},
|
||||
{-0.1f, 0.1f, -0.1f, 0.5f, -0.1f, 0.4f, 0.5f, 0.0f, 0.4f},
|
||||
{-0.1f, -0.2f, 0.0f, 0.4f, -0.3f, 0.0f, 0.3f, 0.0f, 0.0f, -0.4f},
|
||||
{0.0f, 0.0f, 0.0f, 0.2f, -0.1f, -0.2f, 0.0f, -0.1f, -0.2f, -0.1f, 0.0f},
|
||||
{0.0f, -0.1f, 0.0f, 0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -0.1f, -0.1f, -0.1f, -0.1f},
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.1f}};
|
||||
|
||||
static private final float[][] DELTA_H = new float[][] {
|
||||
{0.0f},
|
||||
{0.0f, -25.1f},
|
||||
{0.0f, -30.2f, -23.9f},
|
||||
{0.0f, 5.7f, -1.0f, 1.1f},
|
||||
{0.0f, 0.2f, 6.9f, 3.7f, -5.6f},
|
||||
{0.0f, 0.1f, 2.5f, -0.9f, 3.0f, 0.5f},
|
||||
{0.0f, 0.1f, -1.8f, -1.4f, 0.9f, 0.1f, 1.0f},
|
||||
{0.0f, 0.5f, 0.6f, -0.7f, -0.2f, -1.2f, 0.2f, 0.3f},
|
||||
{0.0f, -0.3f, 0.7f, -0.2f, 0.5f, -0.3f, -0.5f, 0.4f, 0.1f},
|
||||
{0.0f, -0.3f, 0.2f, -0.4f, 0.4f, 0.1f, 0.0f, -0.2f, 0.5f, 0.2f},
|
||||
{0.0f, 0.0f, 0.1f, -0.3f, 0.1f, -0.2f, 0.1f, 0.0f, -0.1f, 0.2f, 0.0f},
|
||||
{0.0f, 0.0f, 0.1f, 0.0f, 0.2f, 0.0f, 0.0f, 0.1f, 0.0f, -0.1f, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, -0.1f, 0.1f, 0.0f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 0.0f, -0.1f}};
|
||||
|
||||
static private final long BASE_TIME = new Calendar.Builder()
|
||||
.setTimeZone(TimeZone.getTimeZone("UTC"))
|
||||
.setDate(2020, Calendar.JANUARY, 1)
|
||||
.build()
|
||||
.getTimeInMillis();
|
||||
|
||||
// The ratio between the Gauss-normalized associated Legendre functions and
|
||||
// the Schmid quasi-normalized ones. Compute these once staticly since they
|
||||
// don't depend on input variables at all.
|
||||
static private final float[][] SCHMIDT_QUASI_NORM_FACTORS =
|
||||
computeSchmidtQuasiNormFactors(G_COEFF.length);
|
||||
|
||||
/**
|
||||
* Estimate the magnetic field at a given point and time.
|
||||
*
|
||||
* @param gdLatitudeDeg
|
||||
* Latitude in WGS84 geodetic coordinates -- positive is east.
|
||||
* @param gdLongitudeDeg
|
||||
* Longitude in WGS84 geodetic coordinates -- positive is north.
|
||||
* @param altitudeMeters
|
||||
* Altitude in WGS84 geodetic coordinates, in meters.
|
||||
* @param timeMillis
|
||||
* Time at which to evaluate the declination, in milliseconds
|
||||
* since January 1, 1970. (approximate is fine -- the declination
|
||||
* changes very slowly).
|
||||
*/
|
||||
public GeomagneticField(float gdLatitudeDeg,
|
||||
float gdLongitudeDeg,
|
||||
float altitudeMeters,
|
||||
long timeMillis) {
|
||||
final int MAX_N = G_COEFF.length; // Maximum degree of the coefficients.
|
||||
|
||||
// We don't handle the north and south poles correctly -- pretend that
|
||||
// we're not quite at them to avoid crashing.
|
||||
gdLatitudeDeg = Math.min(90.0f - 1e-5f,
|
||||
Math.max(-90.0f + 1e-5f, gdLatitudeDeg));
|
||||
computeGeocentricCoordinates(gdLatitudeDeg,
|
||||
gdLongitudeDeg,
|
||||
altitudeMeters);
|
||||
|
||||
assert G_COEFF.length == H_COEFF.length;
|
||||
|
||||
// Note: LegendreTable computes associated Legendre functions for
|
||||
// cos(theta). We want the associated Legendre functions for
|
||||
// sin(latitude), which is the same as cos(PI/2 - latitude), except the
|
||||
// derivate will be negated.
|
||||
LegendreTable legendre =
|
||||
new LegendreTable(MAX_N - 1,
|
||||
(float)(Math.PI / 2.0 - mGcLatitudeRad));
|
||||
|
||||
// Compute a table of (EARTH_REFERENCE_RADIUS_KM / radius)^n for i in
|
||||
// 0..MAX_N-2 (this is much faster than calling Math.pow MAX_N+1 times).
|
||||
float[] relativeRadiusPower = new float[MAX_N + 2];
|
||||
relativeRadiusPower[0] = 1.0f;
|
||||
relativeRadiusPower[1] = EARTH_REFERENCE_RADIUS_KM / mGcRadiusKm;
|
||||
for (int i = 2; i < relativeRadiusPower.length; ++i) {
|
||||
relativeRadiusPower[i] = relativeRadiusPower[i - 1] *
|
||||
relativeRadiusPower[1];
|
||||
}
|
||||
|
||||
// Compute tables of sin(lon * m) and cos(lon * m) for m = 0..MAX_N --
|
||||
// this is much faster than calling Math.sin and Math.com MAX_N+1 times.
|
||||
float[] sinMLon = new float[MAX_N];
|
||||
float[] cosMLon = new float[MAX_N];
|
||||
sinMLon[0] = 0.0f;
|
||||
cosMLon[0] = 1.0f;
|
||||
sinMLon[1] = (float)Math.sin(mGcLongitudeRad);
|
||||
cosMLon[1] = (float)Math.cos(mGcLongitudeRad);
|
||||
|
||||
for (int m = 2; m < MAX_N; ++m) {
|
||||
// Standard expansions for sin((m-x)*theta + x*theta) and
|
||||
// cos((m-x)*theta + x*theta).
|
||||
int x = m >> 1;
|
||||
sinMLon[m] = sinMLon[m - x] * cosMLon[x] + cosMLon[m - x] * sinMLon[x];
|
||||
cosMLon[m] = cosMLon[m - x] * cosMLon[x] - sinMLon[m - x] * sinMLon[x];
|
||||
}
|
||||
|
||||
float inverseCosLatitude = 1.0f / (float)Math.cos(mGcLatitudeRad);
|
||||
float yearsSinceBase =
|
||||
(timeMillis - BASE_TIME) / (365f * 24f * 60f * 60f * 1000f);
|
||||
|
||||
// We now compute the magnetic field strength given the geocentric
|
||||
// location. The magnetic field is the derivative of the potential
|
||||
// function defined by the model. See NOAA Technical Report: The US/UK
|
||||
// World Magnetic Model for 2020-2025 for the derivation.
|
||||
float gcX = 0.0f; // Geocentric northwards component.
|
||||
float gcY = 0.0f; // Geocentric eastwards component.
|
||||
float gcZ = 0.0f; // Geocentric downwards component.
|
||||
|
||||
for (int n = 1; n < MAX_N; n++) {
|
||||
for (int m = 0; m <= n; m++) {
|
||||
// Adjust the coefficients for the current date.
|
||||
float g = G_COEFF[n][m] + yearsSinceBase * DELTA_G[n][m];
|
||||
float h = H_COEFF[n][m] + yearsSinceBase * DELTA_H[n][m];
|
||||
|
||||
// Negative derivative with respect to latitude, divided by
|
||||
// radius. This looks like the negation of the version in the
|
||||
// NOAA Technical report because that report used
|
||||
// P_n^m(sin(theta)) and we use P_n^m(cos(90 - theta)), so the
|
||||
// derivative with respect to theta is negated.
|
||||
gcX += relativeRadiusPower[n + 2] * (g * cosMLon[m] + h * sinMLon[m]) * legendre.mPDeriv[n][m] * SCHMIDT_QUASI_NORM_FACTORS[n][m];
|
||||
|
||||
// Negative derivative with respect to longitude, divided by
|
||||
// radius.
|
||||
gcY += relativeRadiusPower[n + 2] * m * (g * sinMLon[m] - h * cosMLon[m]) * legendre.mP[n][m] * SCHMIDT_QUASI_NORM_FACTORS[n][m] * inverseCosLatitude;
|
||||
|
||||
// Negative derivative with respect to radius.
|
||||
gcZ -= (n + 1) * relativeRadiusPower[n + 2] * (g * cosMLon[m] + h * sinMLon[m]) * legendre.mP[n][m] * SCHMIDT_QUASI_NORM_FACTORS[n][m];
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to geodetic coordinates. This is basically just a
|
||||
// rotation around the Y-axis by the difference in latitudes between the
|
||||
// geocentric frame and the geodetic frame.
|
||||
double latDiffRad = Math.toRadians(gdLatitudeDeg) - mGcLatitudeRad;
|
||||
mX = (float)(gcX * Math.cos(latDiffRad) + gcZ * Math.sin(latDiffRad));
|
||||
mY = gcY;
|
||||
mZ = (float)(-gcX * Math.sin(latDiffRad) + gcZ * Math.cos(latDiffRad));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The X (northward) component of the magnetic field in nanoteslas.
|
||||
*/
|
||||
public float getX() {
|
||||
return mX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Y (eastward) component of the magnetic field in nanoteslas.
|
||||
*/
|
||||
public float getY() {
|
||||
return mY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Z (downward) component of the magnetic field in nanoteslas.
|
||||
*/
|
||||
public float getZ() {
|
||||
return mZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The declination of the horizontal component of the magnetic
|
||||
* field from true north, in degrees (i.e. positive means the
|
||||
* magnetic field is rotated east that much from true north).
|
||||
*/
|
||||
public float getDeclination() {
|
||||
return (float)Math.toDegrees(Math.atan2(mY, mX));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The inclination of the magnetic field in degrees -- positive
|
||||
* means the magnetic field is rotated downwards.
|
||||
*/
|
||||
public float getInclination() {
|
||||
return (float)Math.toDegrees(Math.atan2(mZ,
|
||||
getHorizontalStrength()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Horizontal component of the field strength in nanoteslas.
|
||||
*/
|
||||
public float getHorizontalStrength() {
|
||||
return (float)Math.hypot(mX, mY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Total field strength in nanoteslas.
|
||||
*/
|
||||
public float getFieldStrength() {
|
||||
return (float)Math.sqrt(mX * mX + mY * mY + mZ * mZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param gdLatitudeDeg
|
||||
* Latitude in WGS84 geodetic coordinates.
|
||||
* @param gdLongitudeDeg
|
||||
* Longitude in WGS84 geodetic coordinates.
|
||||
* @param altitudeMeters
|
||||
* Altitude above sea level in WGS84 geodetic coordinates.
|
||||
* @return Geocentric latitude (i.e. angle between closest point on the
|
||||
* equator and this point, at the center of the earth.
|
||||
*/
|
||||
private void computeGeocentricCoordinates(float gdLatitudeDeg,
|
||||
float gdLongitudeDeg,
|
||||
float altitudeMeters) {
|
||||
float altitudeKm = altitudeMeters / 1000.0f;
|
||||
float a2 = EARTH_SEMI_MAJOR_AXIS_KM * EARTH_SEMI_MAJOR_AXIS_KM;
|
||||
float b2 = EARTH_SEMI_MINOR_AXIS_KM * EARTH_SEMI_MINOR_AXIS_KM;
|
||||
double gdLatRad = Math.toRadians(gdLatitudeDeg);
|
||||
float clat = (float)Math.cos(gdLatRad);
|
||||
float slat = (float)Math.sin(gdLatRad);
|
||||
float tlat = slat / clat;
|
||||
float latRad =
|
||||
(float)Math.sqrt(a2 * clat * clat + b2 * slat * slat);
|
||||
|
||||
mGcLatitudeRad = (float)Math.atan(tlat * (latRad * altitudeKm + b2) / (latRad * altitudeKm + a2));
|
||||
|
||||
mGcLongitudeRad = (float)Math.toRadians(gdLongitudeDeg);
|
||||
|
||||
float radSq = altitudeKm * altitudeKm + 2 * altitudeKm * (float)Math.sqrt(a2 * clat * clat + b2 * slat * slat) + (a2 * a2 * clat * clat + b2 * b2 * slat * slat) / (a2 * clat * clat + b2 * slat * slat);
|
||||
mGcRadiusKm = (float)Math.sqrt(radSq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to compute a table of Gauss-normalized associated Legendre
|
||||
* functions P_n^m(cos(theta))
|
||||
*/
|
||||
static private class LegendreTable {
|
||||
// These are the Gauss-normalized associated Legendre functions -- that
|
||||
// is, they are normal Legendre functions multiplied by
|
||||
// (n-m)!/(2n-1)!! (where (2n-1)!! = 1*3*5*...*2n-1)
|
||||
public final float[][] mP;
|
||||
|
||||
// Derivative of mP, with respect to theta.
|
||||
public final float[][] mPDeriv;
|
||||
|
||||
/**
|
||||
* @param maxN
|
||||
* The maximum n- and m-values to support
|
||||
* @param thetaRad
|
||||
* Returned functions will be Gauss-normalized
|
||||
* P_n^m(cos(thetaRad)), with thetaRad in radians.
|
||||
*/
|
||||
public LegendreTable(int maxN, float thetaRad) {
|
||||
// Compute the table of Gauss-normalized associated Legendre
|
||||
// functions using standard recursion relations. Also compute the
|
||||
// table of derivatives using the derivative of the recursion
|
||||
// relations.
|
||||
float cos = (float)Math.cos(thetaRad);
|
||||
float sin = (float)Math.sin(thetaRad);
|
||||
|
||||
mP = new float[maxN + 1][];
|
||||
mPDeriv = new float[maxN + 1][];
|
||||
mP[0] = new float[] {1.0f};
|
||||
mPDeriv[0] = new float[] {0.0f};
|
||||
for (int n = 1; n <= maxN; n++) {
|
||||
mP[n] = new float[n + 1];
|
||||
mPDeriv[n] = new float[n + 1];
|
||||
for (int m = 0; m <= n; m++) {
|
||||
if (n == m) {
|
||||
mP[n][m] = sin * mP[n - 1][m - 1];
|
||||
mPDeriv[n][m] = cos * mP[n - 1][m - 1] + sin * mPDeriv[n - 1][m - 1];
|
||||
} else if (n == 1 || m == n - 1) {
|
||||
mP[n][m] = cos * mP[n - 1][m];
|
||||
mPDeriv[n][m] = -sin * mP[n - 1][m] + cos * mPDeriv[n - 1][m];
|
||||
} else {
|
||||
assert n > 1 && m < n - 1;
|
||||
float k = ((n - 1) * (n - 1) - m * m) / (float)((2 * n - 1) * (2 * n - 3));
|
||||
mP[n][m] = cos * mP[n - 1][m] - k * mP[n - 2][m];
|
||||
mPDeriv[n][m] = -sin * mP[n - 1][m] + cos * mPDeriv[n - 1][m] - k * mPDeriv[n - 2][m];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the ration between the Gauss-normalized associated Legendre
|
||||
* functions and the Schmidt quasi-normalized version. This is equivalent to
|
||||
* sqrt((m==0?1:2)*(n-m)!/(n+m!))*(2n-1)!!/(n-m)!
|
||||
*/
|
||||
private static float[][] computeSchmidtQuasiNormFactors(int maxN) {
|
||||
float[][] schmidtQuasiNorm = new float[maxN + 1][];
|
||||
schmidtQuasiNorm[0] = new float[] {1.0f};
|
||||
for (int n = 1; n <= maxN; n++) {
|
||||
schmidtQuasiNorm[n] = new float[n + 1];
|
||||
schmidtQuasiNorm[n][0] =
|
||||
schmidtQuasiNorm[n - 1][0] * (2 * n - 1) / (float)n;
|
||||
for (int m = 1; m <= n; m++) {
|
||||
schmidtQuasiNorm[n][m] = schmidtQuasiNorm[n][m - 1] * (float)Math.sqrt((n - m + 1) * (m == 1 ? 2 : 1) / (float)(n + m));
|
||||
}
|
||||
}
|
||||
return schmidtQuasiNorm;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ public class SensorManager {
|
|||
new LocationManager().requestLocationUpdates(null, 0, 0, new LocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
listener.onSensorChanged(new SensorEvent(new float[]{(float)location.getBearing()}, sensor));
|
||||
listener.onSensorChanged(new SensorEvent(new float[]{location.getBearing()}, sensor));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
|
|
@ -4,12 +4,27 @@ public class Location {
|
|||
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
private double altitude;
|
||||
private double accuracy;
|
||||
private double speed;
|
||||
private double bearing;
|
||||
private long timestamp;
|
||||
|
||||
public Location (double latitude, double longitude, double bearing) {
|
||||
/* for internal use */
|
||||
public Location (double latitude,
|
||||
double longitude,
|
||||
double altitude,
|
||||
double accuracy,
|
||||
double speed,
|
||||
double bearing,
|
||||
long timestamp) {
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.altitude = altitude;
|
||||
this.accuracy = accuracy;
|
||||
this.speed = speed;
|
||||
this.bearing = bearing;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
|
@ -20,8 +35,43 @@ public class Location {
|
|||
return longitude;
|
||||
}
|
||||
|
||||
public double getBearing() {
|
||||
return bearing;
|
||||
public boolean hasAltitude() {
|
||||
return altitude != -Double.MAX_VALUE;
|
||||
}
|
||||
|
||||
public double getAltitude() {
|
||||
return altitude;
|
||||
}
|
||||
|
||||
public boolean hasAccuracy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public float getAccuracy() {
|
||||
return (float)accuracy;
|
||||
}
|
||||
|
||||
public boolean hasSpeed() {
|
||||
return speed != -1;
|
||||
}
|
||||
|
||||
public float getSpeed() {
|
||||
return (float)speed;
|
||||
}
|
||||
|
||||
public boolean hasBearing() {
|
||||
return bearing != -1;
|
||||
}
|
||||
|
||||
public float getBearing() {
|
||||
return (float)bearing;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getProvider() {
|
||||
return "fused";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package android.location;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.lang.Runnable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -26,9 +29,15 @@ public class LocationManager {
|
|||
|
||||
private native void nativeGetLocation();
|
||||
|
||||
private static void locationUpdated(double latitude, double longitude, double heading) {
|
||||
private static void locationUpdated(double latitude,
|
||||
double longitude,
|
||||
double altitude,
|
||||
double accuracy,
|
||||
double speed,
|
||||
double bearing,
|
||||
long timestamp) {
|
||||
for (LocationListener locationListener : listeners) {
|
||||
locationListener.onLocationChanged(new Location(latitude, longitude, heading));
|
||||
locationListener.onLocationChanged(new Location(latitude, longitude, altitude, accuracy, speed, bearing, timestamp));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,4 +51,21 @@ public class LocationManager {
|
|||
public List<String> getAllProviders() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public List<String> getProviders(boolean enabledOnly) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean registerGnssStatusCallback(GnssStatus.Callback callback, Handler handler) {
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onSatelliteStatusChanged(new GnssStatus());
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public void unregisterGnssStatusCallback(GnssStatus.Callback callback) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package android.net;
|
|||
|
||||
import android.os.Handler;
|
||||
|
||||
class NetworkCapabilities {}
|
||||
|
||||
public class ConnectivityManager {
|
||||
|
||||
public class NetworkCallback {
|
||||
|
@ -35,10 +33,14 @@ public class ConnectivityManager {
|
|||
return new Network();
|
||||
}
|
||||
|
||||
public void registerDefaultNetworkCallback(NetworkCallback cb, Handler hdl) {}
|
||||
public Network[] getAllNetworks() {
|
||||
return new Network[] { getActiveNetwork() };
|
||||
}
|
||||
|
||||
public NetworkCapabilities getNetworkCapabilities(Network network) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerDefaultNetworkCallback(NetworkCallback cb, Handler hdl) {}
|
||||
|
||||
}
|
||||
|
|
7
src/api-impl/android/net/NetworkCapabilities.java
Normal file
7
src/api-impl/android/net/NetworkCapabilities.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package android.net;
|
||||
|
||||
public final class NetworkCapabilities {
|
||||
public boolean hasCapability(int capability) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -12,7 +12,12 @@ public class BaseBundle {
|
|||
// Invariant - exactly one of mMap / mParcelledData will be null
|
||||
// (except inside a call to unparcel)
|
||||
|
||||
/* package */ ArrayMap<String, Object> mMap = new ArrayMap<>();
|
||||
/* package */ ArrayMap<String, Object> mMap;
|
||||
|
||||
public BaseBundle() {
|
||||
mMap = new ArrayMap<String, Object>();
|
||||
}
|
||||
|
||||
|
||||
// Log a message if the value was non-null but not of the expected type
|
||||
void typeWarning(String key, Object value, String className,
|
||||
|
|
|
@ -107,6 +107,11 @@ public class Build {
|
|||
* Various version strings.
|
||||
*/
|
||||
public static class VERSION {
|
||||
static {
|
||||
String SDK_INT_str = System.getProperty("Build.VERSION.SDK_INT");
|
||||
SDK_INT = (SDK_INT_str != null) ? Integer.parseInt(SDK_INT_str) : Build.VERSION_CODES.GINGERBREAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal value used by the underlying source control to
|
||||
* represent this build. E.g., a perforce changelist number
|
||||
|
@ -123,7 +128,7 @@ public class Build {
|
|||
* The user-visible SDK version of the framework; its possible
|
||||
* values are defined in {@link Build.VERSION_CODES}.
|
||||
*/
|
||||
public static final int SDK_INT = Build.VERSION_CODES.GINGERBREAD;
|
||||
public static final int SDK_INT;
|
||||
|
||||
/**
|
||||
* The user-visible SDK version of the framework in its raw String
|
||||
|
|
|
@ -57,7 +57,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
|
|||
* Constructs a new, empty Bundle.
|
||||
*/
|
||||
public Bundle() {
|
||||
mMap = new ArrayMap<String, Object>();
|
||||
super();
|
||||
mClassLoader = getClass().getClassLoader();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,27 @@ package android.os;
|
|||
|
||||
public class SystemProperties {
|
||||
public static String get(String prop) {
|
||||
android.util.Log.i("SystemProperties", "Grabbing prop " + prop);
|
||||
return null;
|
||||
android.util.Log.i("SystemProperties", "Grabbing String prop " + prop);
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String get(String prop, String def) {
|
||||
android.util.Log.i("SystemProperties", "Grabbing String prop " + prop + ", default " + def);
|
||||
return def;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String prop, boolean def) {
|
||||
android.util.Log.i("SystemProperties", "Grabbing prop " + prop + ", default " + def);
|
||||
android.util.Log.i("SystemProperties", "Grabbing boolean prop " + prop + ", default " + def);
|
||||
return def;
|
||||
}
|
||||
|
||||
public static int getInt(String prop, int def) {
|
||||
android.util.Log.i("SystemProperties", "Grabbing int prop " + prop + ", default " + def);
|
||||
return def;
|
||||
}
|
||||
|
||||
public static long getLong(String prop, long def) {
|
||||
android.util.Log.i("SystemProperties", "Grabbing long prop " + prop + ", default " + def);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
package android.provider;
|
||||
|
||||
public interface BaseColumns {}
|
||||
public interface BaseColumns {
|
||||
public static final String _ID = "_id";
|
||||
public static final String _COUNT = "_count";
|
||||
}
|
||||
|
|
|
@ -6,9 +6,13 @@ public class ContactsContract {
|
|||
|
||||
public static final class CommonDataKinds {
|
||||
|
||||
public static class Phone {
|
||||
public static final class Phone {
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://com.android.contacts/phones");
|
||||
}
|
||||
|
||||
public static final class Email {
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://com.android.contacts/emails");
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Profile {
|
||||
|
|
|
@ -6,6 +6,12 @@ import android.util.AndroidException;
|
|||
|
||||
public class Settings {
|
||||
public static final class Secure {
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://settings/secure");
|
||||
|
||||
public static Uri getUriFor(String name) {
|
||||
return Uri.withAppendedPath(CONTENT_URI, name);
|
||||
}
|
||||
|
||||
public static String getString(ContentResolver content_resolver, String key) {
|
||||
switch (key) {
|
||||
case "android_id":
|
||||
|
@ -25,6 +31,8 @@ public class Settings {
|
|||
switch (key) {
|
||||
case "limit_ad_tracking":
|
||||
return 1; // obviously, duh
|
||||
case "user_setup_complete":
|
||||
return 1;
|
||||
default:
|
||||
java.lang.System.out.println("!!!! Settings$Secure.getInt: unknown key: >" + key + "<");
|
||||
return def;
|
||||
|
|
191
src/api-impl/android/provider/UserDictionary.java
Normal file
191
src/api-impl/android/provider/UserDictionary.java
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.provider;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A provider of user defined words for input methods to use for predictive text input.
|
||||
* Applications and input methods may add words into the dictionary. Words can have associated
|
||||
* frequency information and locale information.
|
||||
*
|
||||
* <p><strong>NOTE: </strong>Starting on API 23, the user dictionary is only accessible through
|
||||
* IME and spellchecker.
|
||||
*/
|
||||
public class UserDictionary {
|
||||
|
||||
/**
|
||||
* Authority string for this provider.
|
||||
*/
|
||||
public static final String AUTHORITY = "user_dictionary";
|
||||
|
||||
/**
|
||||
* The content:// style URL for this provider
|
||||
*/
|
||||
public static final Uri CONTENT_URI =
|
||||
Uri.parse("content://" + AUTHORITY);
|
||||
|
||||
private static final int FREQUENCY_MIN = 0;
|
||||
private static final int FREQUENCY_MAX = 255;
|
||||
|
||||
/**
|
||||
* Contains the user defined words.
|
||||
*/
|
||||
public static class Words implements BaseColumns {
|
||||
/**
|
||||
* The content:// style URL for this table
|
||||
*/
|
||||
public static final Uri CONTENT_URI =
|
||||
Uri.parse("content://" + AUTHORITY + "/words");
|
||||
|
||||
/**
|
||||
* The MIME type of {@link #CONTENT_URI} providing a directory of words.
|
||||
*/
|
||||
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.userword";
|
||||
|
||||
/**
|
||||
* The MIME type of a {@link #CONTENT_URI} sub-directory of a single word.
|
||||
*/
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.userword";
|
||||
|
||||
public static final String _ID = BaseColumns._ID;
|
||||
|
||||
/**
|
||||
* The word column.
|
||||
* <p>TYPE: TEXT</p>
|
||||
*/
|
||||
public static final String WORD = "word";
|
||||
|
||||
/**
|
||||
* The frequency column. A value between 1 and 255. Higher values imply higher frequency.
|
||||
* <p>TYPE: INTEGER</p>
|
||||
*/
|
||||
public static final String FREQUENCY = "frequency";
|
||||
|
||||
/**
|
||||
* The locale that this word belongs to. Null if it pertains to all
|
||||
* locales. Locale is as defined by the string returned by Locale.toString().
|
||||
* <p>TYPE: TEXT</p>
|
||||
*/
|
||||
public static final String LOCALE = "locale";
|
||||
|
||||
/**
|
||||
* The uid of the application that inserted the word.
|
||||
* <p>TYPE: INTEGER</p>
|
||||
*/
|
||||
public static final String APP_ID = "appid";
|
||||
|
||||
/**
|
||||
* An optional shortcut for this word. When the shortcut is typed, supporting IMEs should
|
||||
* suggest the word in this row as an alternate spelling too.
|
||||
*/
|
||||
public static final String SHORTCUT = "shortcut";
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #addWord(Context, String, int, String, Locale)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int LOCALE_TYPE_ALL = 0;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #addWord(Context, String, int, String, Locale)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int LOCALE_TYPE_CURRENT = 1;
|
||||
|
||||
/**
|
||||
* Sort by descending order of frequency.
|
||||
*/
|
||||
public static final String DEFAULT_SORT_ORDER = FREQUENCY + " DESC";
|
||||
|
||||
/**
|
||||
* Adds a word to the dictionary, with the given frequency and the specified
|
||||
* specified locale type.
|
||||
*
|
||||
* @deprecated Please use
|
||||
* {@link #addWord(Context, String, int, String, Locale)} instead.
|
||||
*
|
||||
* @param context the current application context
|
||||
* @param word the word to add to the dictionary. This should not be null or
|
||||
* empty.
|
||||
* @param localeType the locale type for this word. It should be one of
|
||||
* {@link #LOCALE_TYPE_ALL} or {@link #LOCALE_TYPE_CURRENT}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void addWord(Context context, String word,
|
||||
int frequency, int localeType) {
|
||||
|
||||
if (localeType != LOCALE_TYPE_ALL && localeType != LOCALE_TYPE_CURRENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Locale locale;
|
||||
|
||||
if (localeType == LOCALE_TYPE_CURRENT) {
|
||||
locale = Locale.getDefault();
|
||||
} else {
|
||||
locale = null;
|
||||
}
|
||||
|
||||
addWord(context, word, frequency, null, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a word to the dictionary, with the given frequency and the specified
|
||||
* locale type.
|
||||
*
|
||||
* @param context the current application context
|
||||
* @param word the word to add to the dictionary. This should not be null or
|
||||
* empty.
|
||||
* @param shortcut optional shortcut spelling for this word. When the shortcut
|
||||
* is typed, the word may be suggested by applications that support it. May be null.
|
||||
* @param locale the locale to insert the word for, or null to insert the word
|
||||
* for all locales.
|
||||
*/
|
||||
public static void addWord(Context context, String word,
|
||||
int frequency, String shortcut, Locale locale) {
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
|
||||
if (TextUtils.isEmpty(word)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (frequency < FREQUENCY_MIN)
|
||||
frequency = FREQUENCY_MIN;
|
||||
if (frequency > FREQUENCY_MAX)
|
||||
frequency = FREQUENCY_MAX;
|
||||
|
||||
final int COLUMN_COUNT = 5;
|
||||
ContentValues values = new ContentValues(COLUMN_COUNT);
|
||||
|
||||
values.put(WORD, word);
|
||||
values.put(FREQUENCY, frequency);
|
||||
values.put(LOCALE, null == locale ? null : locale.toString());
|
||||
values.put(APP_ID, 0); // TODO: Get App UID
|
||||
values.put(SHORTCUT, shortcut);
|
||||
|
||||
Uri result = resolver.insert(CONTENT_URI, values);
|
||||
// It's ok if the insert doesn't succeed because the word
|
||||
// already exists.
|
||||
}
|
||||
}
|
||||
}
|
10
src/api-impl/android/text/AutoText.java
Normal file
10
src/api-impl/android/text/AutoText.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package android.text;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
public class AutoText {
|
||||
|
||||
public static String get(CharSequence src, final int start, final int end, View view) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* most of this file:
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -18,11 +18,11 @@
|
|||
|
||||
package android.text;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
public class TextUtils {
|
||||
public static int getLayoutDirectionFromLocale(Locale locale) {
|
||||
return 0 /*LTR*/; // FIXME
|
||||
|
@ -255,7 +255,7 @@ public class TextUtils {
|
|||
}
|
||||
|
||||
if (buf == null || buf.length < len)
|
||||
buf = ArrayUtils.newUnpaddedCharArray(len);
|
||||
buf = ArrayUtils.newUnpaddedCharArray(len);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -377,4 +377,80 @@ public class TextUtils {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for splitting strings according to rules that are opaque to the user of this
|
||||
* interface. This also has less overhead than split, which uses regular expressions and
|
||||
* allocates an array to hold the results.
|
||||
*
|
||||
* <p>The most efficient way to use this class is:
|
||||
*
|
||||
* <pre>
|
||||
* // Once
|
||||
* TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(delimiter);
|
||||
*
|
||||
* // Once per string to split
|
||||
* splitter.setString(string);
|
||||
* for (String s : splitter) {
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public interface StringSplitter extends Iterable<String> {
|
||||
public void setString(String string);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple string splitter.
|
||||
*
|
||||
* <p>If the final character in the string to split is the delimiter then no empty string will
|
||||
* be returned for the empty string after that delimeter. That is, splitting <tt>"a,b,"</tt> on
|
||||
* comma will return <tt>"a", "b"</tt>, not <tt>"a", "b", ""</tt>.
|
||||
*/
|
||||
public static class SimpleStringSplitter implements StringSplitter, Iterator<String> {
|
||||
private String mString;
|
||||
private char mDelimiter;
|
||||
private int mPosition;
|
||||
private int mLength;
|
||||
|
||||
/**
|
||||
* Initializes the splitter. setString may be called later.
|
||||
* @param delimiter the delimeter on which to split
|
||||
*/
|
||||
public SimpleStringSplitter(char delimiter) {
|
||||
mDelimiter = delimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the string to split
|
||||
* @param string the string to split
|
||||
*/
|
||||
public void setString(String string) {
|
||||
mString = string;
|
||||
mPosition = 0;
|
||||
mLength = mString.length();
|
||||
}
|
||||
|
||||
public Iterator<String> iterator() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return mPosition < mLength;
|
||||
}
|
||||
|
||||
public String next() {
|
||||
int end = mString.indexOf(mDelimiter, mPosition);
|
||||
if (end == -1) {
|
||||
end = mLength;
|
||||
}
|
||||
String nextString = mString.substring(mPosition, end);
|
||||
mPosition = end + 1; // Skip the delimiter.
|
||||
return nextString;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package android.text.style;
|
||||
|
||||
public class BackgroundColorSpan {
|
||||
public class BackgroundColorSpan extends CharacterStyle {
|
||||
public BackgroundColorSpan(int color) {}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package android.text.style;
|
||||
|
||||
public class UnderlineSpan {
|
||||
public class UnderlineSpan extends CharacterStyle {
|
||||
}
|
||||
|
|
|
@ -398,6 +398,23 @@ public class TypedValue {
|
|||
return res;
|
||||
}
|
||||
|
||||
public int getComplexUnit() {
|
||||
return (data >> COMPLEX_UNIT_SHIFT) & COMPLEX_UNIT_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the complex unit type for the given complex dimension. For example, a dimen type
|
||||
* with value 12sp will return {@link #COMPLEX_UNIT_SP}. Use with values created with {@link
|
||||
* #createComplexDimension(int, int)} etc.
|
||||
*
|
||||
* @return The complex unit type.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static int getUnitFromComplexDimension(int complexDimension) {
|
||||
return COMPLEX_UNIT_MASK & (complexDimension >> TypedValue.COMPLEX_UNIT_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an unpacked complex data value holding a dimension to its final floating
|
||||
* point value. The two parameters <var>unit</var> and <var>value</var>
|
||||
|
@ -572,8 +589,4 @@ public class TypedValue {
|
|||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getComplexUnit() {
|
||||
return (data >> COMPLEX_UNIT_SHIFT) & COMPLEX_UNIT_MASK;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ public class LayoutInflater {
|
|||
return mFactory;
|
||||
}
|
||||
|
||||
public final void setFactory(LayoutInflater.Factory factory){
|
||||
public void setFactory(LayoutInflater.Factory factory){
|
||||
mFactory = factory;
|
||||
}
|
||||
|
||||
|
|
|
@ -1075,13 +1075,22 @@ public class View implements Drawable.Callback {
|
|||
}
|
||||
|
||||
private OnTouchListener on_touch_listener = null;
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
|
||||
public boolean onTouchEventInternal(MotionEvent event) {
|
||||
boolean handled = false;
|
||||
if (on_touch_listener != null)
|
||||
handled = on_touch_listener.onTouch(this, event);
|
||||
|
||||
if (!handled)
|
||||
handled = onTouchEvent(event);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setOnTouchListener(OnTouchListener l) {
|
||||
nativeSetOnTouchListener(widget);
|
||||
on_touch_listener = l;
|
||||
|
@ -1206,12 +1215,21 @@ public class View implements Drawable.Callback {
|
|||
|
||||
public native void setBackgroundColor(int color);
|
||||
public native void native_setVisibility(long widget, int visibility, float alpha);
|
||||
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
}
|
||||
|
||||
protected void dispatchVisibilityChanged(View changedView, int visibility) {
|
||||
onVisibilityChanged(changedView, visibility);
|
||||
}
|
||||
|
||||
public void setVisibility(int visibility) {
|
||||
native_setVisibility(widget, visibility, alpha);
|
||||
if ((visibility == View.GONE) != (this.visibility == View.GONE)) {
|
||||
requestLayout();
|
||||
}
|
||||
this.visibility = visibility;
|
||||
dispatchVisibilityChanged(this, visibility);
|
||||
}
|
||||
|
||||
public void setPadding(int left, int top, int right, int bottom) {
|
||||
|
|
|
@ -61,6 +61,10 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
|
|||
addView(child, params);
|
||||
}
|
||||
|
||||
public void addView(View child, int index, LayoutParams params) {
|
||||
addViewInternal(child, index, params);
|
||||
}
|
||||
|
||||
protected void addViewInternal(View child, int index, LayoutParams params) {
|
||||
if (child.parent == this)
|
||||
return;
|
||||
|
@ -81,10 +85,13 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
|
|||
requestLayout();
|
||||
}
|
||||
|
||||
public void addView(View child, int index, LayoutParams params) {
|
||||
addViewInternal(child, index, params);
|
||||
/* We never call this ourselves */
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
return native_dispatchTouchEvent(widget, event, event.getX(), event.getY());
|
||||
}
|
||||
|
||||
|
||||
protected boolean addViewInLayout(View child, int index, LayoutParams params) {
|
||||
addViewInternal(child, index, params);
|
||||
return true;
|
||||
|
@ -169,6 +176,16 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchVisibilityChanged(View changedView, int visibility) {
|
||||
if (children == null) // happens if this gets called during super constructor
|
||||
return;
|
||||
|
||||
for (View child: children) {
|
||||
child.dispatchVisibilityChanged(changedView, visibility);
|
||||
}
|
||||
}
|
||||
|
||||
protected native void native_addView(long widget, long child, int index, LayoutParams params);
|
||||
protected native void native_removeView(long widget, long child);
|
||||
@Override
|
||||
|
@ -636,4 +653,6 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
|
|||
}
|
||||
|
||||
public void requestChildFocus(View child, View focused) {}
|
||||
|
||||
public native boolean native_dispatchTouchEvent(long widget, MotionEvent event, double x, double y);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import android.view.View;
|
|||
|
||||
public class PopupWindow {
|
||||
|
||||
int input_method_mode = 0;
|
||||
|
||||
public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
popover = native_constructor();
|
||||
}
|
||||
|
@ -41,23 +43,25 @@ public class PopupWindow {
|
|||
public void onDismiss();
|
||||
}
|
||||
|
||||
protected native long native_constructor();
|
||||
protected native void native_setContentView(long widget, long contentView);
|
||||
protected native void native_showAsDropDown(long widget, long anchor, int xoff, int yoff, int gravity);
|
||||
protected native boolean native_isShowing(long widget);
|
||||
protected native void native_dismiss(long widget);
|
||||
protected native void native_update(long widget, long anchor, int xoff, int yoff, int width, int height);
|
||||
public void setBackgroundDrawable(Drawable background) {
|
||||
/* FIXME: use a decorview? */
|
||||
if(contentView != null) {
|
||||
contentView.setBackgroundDrawable(background);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBackgroundDrawable(Drawable background) {}
|
||||
public void setInputMethodMode(int mode) {
|
||||
input_method_mode = mode;
|
||||
}
|
||||
|
||||
public void setInputMethodMode(int mode) {}
|
||||
public int getInputMethodMode() {
|
||||
return input_method_mode;
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return native_isShowing(popover);
|
||||
}
|
||||
|
||||
public native void setOnDismissListener(OnDismissListener listener);
|
||||
|
||||
public void setFocusable(boolean focusable) {}
|
||||
|
||||
public Drawable getBackground() {return null;}
|
||||
|
@ -70,17 +74,16 @@ public class PopupWindow {
|
|||
native_setContentView(popover, view == null ? 0 : view.widget);
|
||||
}
|
||||
|
||||
public int getInputMethodMode() {return 0;}
|
||||
|
||||
public int getMaxAvailableHeight(View anchor, int yOffset) {return 500;}
|
||||
|
||||
public int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreKeyboard) {return 500;}
|
||||
|
||||
public native void setWidth(int width);
|
||||
|
||||
public native void setHeight(int height);
|
||||
|
||||
public void setOutsideTouchable(boolean touchable) {}
|
||||
public void setOutsideTouchable(boolean touchable) {
|
||||
/* FIXME: the semantics are different, this seems to specifically exist for cases
|
||||
* where the popup is *not* modal, so that in addition to the window behind getting
|
||||
* the real event, the popup gets a special MotionEvent.ACTION_OUTSIDE event */
|
||||
native_setTouchModal(popover, touchable);
|
||||
}
|
||||
|
||||
public void setTouchInterceptor(View.OnTouchListener listener) {}
|
||||
|
||||
|
@ -88,9 +91,13 @@ public class PopupWindow {
|
|||
native_showAsDropDown(popover, anchor.widget, xoff, yoff, gravity);
|
||||
}
|
||||
|
||||
public View getContentView() {return contentView;}
|
||||
public View getContentView() {
|
||||
return contentView;
|
||||
}
|
||||
|
||||
public void setTouchable(boolean touchable) {}
|
||||
public void setTouchable(boolean touchable) {
|
||||
native_setTouchable(popover, touchable);
|
||||
}
|
||||
|
||||
public void showAsDropDown(View anchor, int xoff, int yoff) {
|
||||
if (!anchor.isAttachedToWindow()) {
|
||||
|
@ -110,7 +117,9 @@ public class PopupWindow {
|
|||
|
||||
public void setAnimationStyle(int animationStyle) {}
|
||||
|
||||
public void setTouchModal(boolean touchModal) {}
|
||||
public void setTouchModal(boolean touchModal) {
|
||||
native_setTouchModal(popover, touchModal);
|
||||
}
|
||||
|
||||
public void setElevation(float elevation) {}
|
||||
|
||||
|
@ -123,4 +132,53 @@ public class PopupWindow {
|
|||
public void setIsClippedToScreen(boolean isClippedToScreen) {}
|
||||
|
||||
public void setEpicenterBounds(Rect bounds) {}
|
||||
|
||||
public void setClippingEnabled(boolean enabled) {}
|
||||
|
||||
/* TODO: handle LayoutParams.WRAP_CONTENT and LayoutParams.MATCH_PARENT */
|
||||
public void setWidth(int width) {
|
||||
if(width < 0)
|
||||
return;
|
||||
|
||||
native_setWidth(popover, width);
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
if(height < 0)
|
||||
return;
|
||||
|
||||
native_setHeight(popover, height);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return native_getWidth(popover);
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return native_getHeight(popover);
|
||||
}
|
||||
|
||||
public void update(int x, int y, int width, int height) {}
|
||||
|
||||
public void setWindowLayoutMode(int widthSpec, int heightSpec) {}
|
||||
|
||||
|
||||
public boolean isTouchable() {
|
||||
return native_isTouchable(popover);
|
||||
}
|
||||
|
||||
protected native long native_constructor();
|
||||
protected native void native_setContentView(long widget, long contentView);
|
||||
protected native void native_showAsDropDown(long widget, long anchor, int xoff, int yoff, int gravity);
|
||||
protected native boolean native_isShowing(long widget);
|
||||
protected native void native_setTouchable(long widget, boolean touchable);
|
||||
protected native void native_setTouchModal(long widget, boolean touchable);
|
||||
protected native void native_dismiss(long widget);
|
||||
protected native void native_update(long widget, long anchor, int xoff, int yoff, int width, int height);
|
||||
public native void setOnDismissListener(OnDismissListener listener);
|
||||
public native void native_setWidth(long widget, int width);
|
||||
public native void native_setHeight(long widget, int height);
|
||||
public native int native_getWidth(long widget);
|
||||
public native int native_getHeight(long widget);
|
||||
public native boolean native_isTouchable(long widget);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,15 @@ public class TextView extends View {
|
|||
@Override
|
||||
protected native long native_constructor(Context context, AttributeSet attrs);
|
||||
|
||||
public void setText(int resId) {
|
||||
setText(getContext().getResources().getText(resId));
|
||||
}
|
||||
|
||||
public void setText(CharSequence text) {
|
||||
setText(text, null);
|
||||
}
|
||||
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
this.text = text;
|
||||
native_setText(text != null ? text.toString() : null);
|
||||
|
||||
|
@ -97,10 +105,6 @@ public class TextView extends View {
|
|||
requestLayout();
|
||||
}
|
||||
|
||||
public void setText(int resId) {
|
||||
setText(getContext().getResources().getText(resId));
|
||||
}
|
||||
|
||||
private native final void native_set_markup(int bool);
|
||||
|
||||
public native final void native_setText(String text);
|
||||
|
@ -264,10 +268,6 @@ public class TextView extends View {
|
|||
|
||||
public void setTextIsSelectable(boolean selectable) {}
|
||||
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
setText(text);
|
||||
}
|
||||
|
||||
public MovementMethod getMovementMethod() {
|
||||
return new BaseMovementMethod();
|
||||
}
|
||||
|
@ -368,6 +368,10 @@ public class TextView extends View {
|
|||
return 10; // FIXME
|
||||
}
|
||||
|
||||
public int getMaxHeight() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean isAllCaps() { return false; }
|
||||
|
||||
public int getAutoSizeStepGranularity() {
|
||||
|
|
|
@ -9,6 +9,7 @@ srcs = [
|
|||
'android/animation/AnimatorListenerAdapter.java',
|
||||
'android/animation/AnimatorSet.java',
|
||||
'android/animation/ArgbEvaluator.java',
|
||||
'android/animation/FloatEvaluator.java',
|
||||
'android/animation/LayoutTransition.java',
|
||||
'android/animation/ObjectAnimator.java',
|
||||
'android/animation/PropertyValuesHolder.java',
|
||||
|
@ -59,6 +60,8 @@ srcs = [
|
|||
'android/app/UiModeManager.java',
|
||||
'android/app/WallpaperManager.java',
|
||||
'android/app/admin/DevicePolicyManager.java',
|
||||
'android/app/backup/BackupAgentHelper.java',
|
||||
'android/app/backup/BackupManager.java',
|
||||
'android/app/job/JobInfo.java',
|
||||
'android/app/job/JobScheduler.java',
|
||||
'android/app/job/JobService.java',
|
||||
|
@ -226,6 +229,7 @@ srcs = [
|
|||
'android/graphics/drawable/Animatable.java',
|
||||
'android/graphics/drawable/AnimationDrawable.java',
|
||||
'android/graphics/drawable/BitmapDrawable.java',
|
||||
'android/graphics/drawable/ClipDrawable.java',
|
||||
'android/graphics/drawable/ColorDrawable.java',
|
||||
'android/graphics/drawable/ColorStateListDrawable.java',
|
||||
'android/graphics/drawable/Drawable.java',
|
||||
|
@ -246,6 +250,7 @@ srcs = [
|
|||
'android/graphics/drawable/shapes/RoundRectShape.java',
|
||||
'android/graphics/drawable/shapes/Shape.java',
|
||||
'android/hardware/ConsumerIrManager.java',
|
||||
'android/hardware/GeomagneticField.java',
|
||||
'android/hardware/Sensor.java',
|
||||
'android/hardware/SensorEvent.java',
|
||||
'android/hardware/SensorEventListener.java',
|
||||
|
@ -255,6 +260,7 @@ srcs = [
|
|||
'android/hardware/input/InputManager.java',
|
||||
'android/hardware/usb/UsbManager.java',
|
||||
'android/location/Criteria.java',
|
||||
'android/location/GnssStatus.java',
|
||||
'android/location/Location.java',
|
||||
'android/location/LocationListener.java',
|
||||
'android/location/LocationManager.java',
|
||||
|
@ -282,6 +288,7 @@ srcs = [
|
|||
'android/media/tv/TvInputManager.java',
|
||||
'android/net/ConnectivityManager.java',
|
||||
'android/net/Network.java',
|
||||
'android/net/NetworkCapabilities.java',
|
||||
'android/net/NetworkInfo.java',
|
||||
'android/net/NetworkRequest.java',
|
||||
'android/net/SSLCertificateSocketFactory.java',
|
||||
|
@ -357,8 +364,10 @@ srcs = [
|
|||
'android/provider/ContactsContract.java',
|
||||
'android/provider/MediaStore.java',
|
||||
'android/provider/Settings.java',
|
||||
'android/provider/UserDictionary.java',
|
||||
'android/security/keystore/AndroidKeyStore.java',
|
||||
'android/service/media/MediaBrowserService.java',
|
||||
'android/speech/tts/TextToSpeech.java',
|
||||
'android/telecom/ConnectionService.java',
|
||||
'android/telecom/TelecomManager.java',
|
||||
'android/telephony/CellLocation.java',
|
||||
|
@ -366,6 +375,7 @@ srcs = [
|
|||
'android/telephony/PhoneStateListener.java',
|
||||
'android/telephony/SubscriptionManager.java',
|
||||
'android/telephony/TelephonyManager.java',
|
||||
'android/text/AutoText.java',
|
||||
'android/text/BoringLayout.java',
|
||||
'android/text/ClipboardManager.java',
|
||||
'android/text/Editable.java',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue