Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson
2025-01-27 11:38:16 -08:00
committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright 2024 Google LLC
*
* 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.
*/
#pragma once
// These are the stubs that are common between the ancs_pebble_action and timeline_action tests
// This huge list is mainly due to the inclusion of timeline_actions.c which handles both UI and
// a large portion of action logic, which will hopefully be fixed eventually
#include "applib/ui/action_menu_window_private.h"
#include "services/normal/blob_db/ios_notif_pref_db.h"
#include "services/normal/blob_db/sync.h"
#include "services/normal/filesystem/pfs.h"
#include "services/normal/phone_call_util.h"
#include "services/normal/timeline/actions_endpoint.h"
#include "services/normal/timeline/timeline.h"
#include "services/normal/timeline/timeline_actions.h"
#include "util/size.h"
#include "stubs_action_chaining_window.h"
#include "stubs_action_menu.h"
#include "stubs_analytics.h"
#include "stubs_app_install_manager.h"
#include "stubs_app_manager.h"
#include "stubs_app_state.h"
#include "stubs_blob_db_sync.h"
#include "stubs_dialog.h"
#include "stubs_event_service_client.h"
#include "stubs_evented_timer.h"
#include "stubs_events.h"
#include "stubs_expandable_dialog.h"
#include "stubs_gcolor.h"
#include "stubs_hexdump.h"
#include "stubs_i18n.h"
#include "stubs_layout_layer.h"
#include "stubs_logging.h"
#include "stubs_modal_manager.h"
#include "stubs_mutex.h"
#include "stubs_notification_storage.h"
#include "stubs_notifications.h"
#include "stubs_passert.h"
#include "stubs_pbl_malloc.h"
#include "stubs_pebble_tasks.h"
#include "stubs_pin_db.h"
#include "stubs_progress_window.h"
#include "stubs_rand_ptr.h"
#include "stubs_regular_timer.h"
#include "stubs_reminder_db.h"
#include "stubs_rtc.h"
#include "stubs_simple_dialog.h"
#include "stubs_task_watchdog.h"
#include "stubs_ui_window.h"
#include "stubs_window_manager.h"
#include "stubs_window_stack.h"
PebblePhoneCaller* phone_call_util_create_caller(const char *number, const char *name) {
return NULL;
}
void launcher_task_add_callback(void (*callback)(void *data), void *data) {
}
void system_task_add_callback(void (*callback)(void *data), void *data) {
}
void ancs_perform_action(uint32_t notification_uid, uint8_t action_id) {
}
status_t blob_db_delete(BlobDBId db_id, const uint8_t *key, int key_len) {
return S_SUCCESS;
}
void timeline_pin_window_push_modal(TimelineItem *item) {
}
CommSession *comm_session_get_system_session(void) {
// This can't be NULL (in that case we don't try to send the message)
return (CommSession *) 1;
}
void comm_session_set_responsiveness(
CommSession *session, BtConsumer consumer, ResponseTimeState state, uint16_t max_period_secs) {
return;
}
void* event_service_claim_buffer(PebbleEvent *e) {
return NULL;
}
void event_service_free_claimed_buffer(void *ref) {
return;
}
void timeline_resources_get_id(const TimelineResourceInfo *timeline_res, TimelineResourceSize size,
AppResourceInfo *res_info) {
return;
}
bool notification_window_is_modal(void) {
return false;
}
size_t string_list_count(StringList *list) {
return 0;
}
char *string_list_get_at(StringList *list, size_t index) {
return NULL;
}
bool alerts_preferences_check_and_set_first_use_complete(int source) {
return true;
}
static TimelineItemActionSource s_current_timeline_action_source =
TimelineItemActionSourceModalNotification;
TimelineItemActionSource kernel_ui_get_current_timeline_item_action_source(void) {
return s_current_timeline_action_source;
}
void kernel_ui_set_current_timeline_item_action_source(TimelineItemActionSource current_source) {
s_current_timeline_action_source = current_source;
}
@@ -0,0 +1,340 @@
/*
* Copyright 2024 Google LLC
*
* 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.
*/
#include "clar.h"
#include "services/normal/notifications/ancs/ancs_notifications.h"
#include "services/normal/notifications/ancs/ancs_notifications_util.h"
#include "services/normal/notifications/ancs/ancs_item.h"
#include "comm/ble/kernel_le_client/ancs/ancs_util.h"
#include "comm/ble/kernel_le_client/ancs/ancs_types.h"
// Test Data
///////////////////////////////////////////////////////////
#include "test_data.h"
// Stubs
///////////////////////////////////////////////////////////
#include "stubs_common.h"
#include "stubs_blob_db_sync_util.h"
#include "stubs_prompt.h"
#include "stubs_sleep.h"
#include "stubs_nexmo.h"
#include "stubs_codepoint.h"
#include "stubs_utf8.h"
// Externs
///////////////////////////////////////////////////////////
extern const int TIMELINE_ACTION_ENDPOINT;
// Fakes / Helpers
///////////////////////////////////////////////////////////
#include "fake_spi_flash.h"
static const uint8_t *s_expected_send_data = NULL;
static bool s_sent_action = false;
bool comm_session_send_data(CommSession *session, uint16_t endpoint_id,
const uint8_t* data, size_t length, uint32_t timeout_ms) {
if (s_expected_send_data == NULL) {
return false;
}
if (endpoint_id != TIMELINE_ACTION_ENDPOINT) {
return false;
}
cl_assert_equal_m(s_expected_send_data, data, length);
s_sent_action = true;
return true;
}
static void prv_support_sms_replies(void) {
// Store the preference in our DB
char *key = "com.apple.MobileSMS";
int key_len = strlen(key);
const int flags = 0;
const int num_attributes = 0;
const int num_actions = 1;
const int action_id = 12;
const int reply_action_attrs = 2; // Title + Emoji
uint8_t val[] = {0, 0, 0, 0, // Flags (unused for now)
num_attributes, num_actions, action_id,
TimelineItemActionTypeAncsResponse, // 0x0D
reply_action_attrs,
AttributeIdTitle, 0x05, 0x00, // Length
0x52, 0x65, 0x70, 0x6c, 0x79, // "Reply"
AttributeIdEmojiSupported, 0x01, 0x00, // Length
0x01, // "Supported"
};
int val_len = sizeof(val);
ios_notif_pref_db_insert((uint8_t *) key, key_len, (void *) &val, val_len);
}
static void prv_support_sms_replies_no_emoji(void) {
// Store the preference in our DB
char *key = "com.apple.MobileSMS";
int key_len = strlen(key);
const int flags = 0;
const int num_attributes = 0;
const int num_actions = 1;
const int action_id = 12;
const int reply_action_attrs = 2; // Title + Emoji
uint8_t val[] = {0, 0, 0, 0, // Flags (unused for now)
num_attributes, num_actions, action_id,
TimelineItemActionTypeAncsResponse, // 0x0D
reply_action_attrs,
AttributeIdTitle, 0x05, 0x00, // Length
0x52, 0x65, 0x70, 0x6c, 0x79, // "Reply"
AttributeIdEmojiSupported, 0x01, 0x00, // Length
0x00, // "Not supported"
};
int val_len = sizeof(val);
ios_notif_pref_db_insert((uint8_t *) key, key_len, (void *) &val, val_len);
}
// Tests
///////////////////////////////////////////////////////////
void test_ancs_pebble_actions__initialize(void) {
s_expected_send_data = NULL;
s_sent_action = false;
fake_spi_flash_init(0, 0x1000000);
pfs_init(false);
pfs_format(false);
}
void test_ancs_pebble_actions__cleanup(void) {
}
void test_ancs_pebble_actions__test_sms_reply(void) {
prv_support_sms_replies();
ANCSAttribute *notif_attributes[NUM_FETCHED_NOTIF_ATTRIBUTES] = {0};
ANCSAttribute *app_attrs[NUM_FETCHED_APP_ATTRIBUTES] = {0};
const size_t header_len = sizeof(GetNotificationAttributesMsg);
bool error = false;
const bool complete = ancs_util_get_attr_ptrs(s_sms_ancs_data + header_len,
ARRAY_LENGTH(s_sms_ancs_data) - header_len,
s_fetched_notif_attributes,
NUM_FETCHED_NOTIF_ATTRIBUTES,
notif_attributes,
&error);
cl_assert(complete);
cl_assert(!error);
time_t timestamp = 0;
ANCSAppMetadata app_metadata = {0};
const ANCSAttribute *app_id = notif_attributes[FetchedNotifAttributeIndexAppID];
iOSNotifPrefs *notif_prefs = ios_notif_pref_db_get_prefs(app_id->value, app_id->length);
TimelineItem *notif = ancs_item_create_and_populate(notif_attributes,
app_attrs,
&app_metadata,
notif_prefs,
timestamp,
ANCSProperty_None);
cl_assert(notif);
cl_assert_equal_i(notif->action_group.num_actions, 2);
cl_assert_equal_i(notif->action_group.actions[0].type, TimelineItemActionTypeAncsNegative);
TimelineItemAction *response_action = &notif->action_group.actions[1];
cl_assert_equal_i(response_action->type, TimelineItemActionTypeAncsResponse);
cl_assert_equal_i(response_action->attr_list.num_attributes, 2);
cl_assert_equal_i(response_action->attr_list.attributes[0].id, AttributeIdTitle);
cl_assert_equal_s(response_action->attr_list.attributes[0].cstring, "Reply");
cl_assert_equal_i(response_action->attr_list.attributes[1].id, AttributeIdEmojiSupported);
cl_assert_equal_i(response_action->attr_list.attributes[1].uint8, 1);
ActionMenuItem menu_item = (ActionMenuItem) {
.action_data = &notif->action_group.actions[1],
};
s_expected_send_data = s_sms_action_data;
timeline_actions_invoke_action(&notif->action_group.actions[1], notif, NULL /*complete_cb*/,
NULL /*cb_data*/);
cl_assert(s_sent_action);
}
void test_ancs_pebble_actions__test_sms_reply_no_emoji(void) {
prv_support_sms_replies_no_emoji();
ANCSAttribute *notif_attributes[NUM_FETCHED_NOTIF_ATTRIBUTES] = {0};
ANCSAttribute *app_attrs[NUM_FETCHED_APP_ATTRIBUTES] = {0};
const size_t header_len = sizeof(GetNotificationAttributesMsg);
bool error = false;
const bool complete = ancs_util_get_attr_ptrs(s_sms_ancs_data + header_len,
ARRAY_LENGTH(s_sms_ancs_data) - header_len,
s_fetched_notif_attributes,
NUM_FETCHED_NOTIF_ATTRIBUTES,
notif_attributes,
&error);
cl_assert(complete);
cl_assert(!error);
time_t timestamp = 0;
ANCSAppMetadata app_metadata = {0};
const ANCSAttribute *app_id = notif_attributes[FetchedNotifAttributeIndexAppID];
iOSNotifPrefs *notif_prefs = ios_notif_pref_db_get_prefs(app_id->value, app_id->length);
TimelineItem *notif = ancs_item_create_and_populate(notif_attributes,
app_attrs,
&app_metadata,
notif_prefs,
timestamp,
ANCSProperty_None);
cl_assert(notif);
cl_assert_equal_i(notif->action_group.num_actions, 2);
cl_assert_equal_i(notif->action_group.actions[0].type, TimelineItemActionTypeAncsNegative);
TimelineItemAction *response_action = &notif->action_group.actions[1];
cl_assert_equal_i(response_action->type, TimelineItemActionTypeAncsResponse);
cl_assert_equal_i(response_action->attr_list.num_attributes, 2);
cl_assert_equal_i(response_action->attr_list.attributes[0].id, AttributeIdTitle);
cl_assert_equal_s(response_action->attr_list.attributes[0].cstring, "Reply");
cl_assert_equal_i(response_action->attr_list.attributes[1].id, AttributeIdEmojiSupported);
cl_assert_equal_i(response_action->attr_list.attributes[1].uint8, 0);
s_expected_send_data = s_sms_action_data;
timeline_actions_invoke_action(&notif->action_group.actions[1], notif, NULL /*complete_cb*/,
NULL /*cb_data*/);
cl_assert(s_sent_action);
}
void test_ancs_pebble_actions__test_sms_replies_unsupported(void) {
prv_support_sms_replies();
ANCSAttribute *notif_attributes[NUM_FETCHED_NOTIF_ATTRIBUTES] = {0};
ANCSAttribute *app_attrs[NUM_FETCHED_APP_ATTRIBUTES] = {0};
const size_t header_len = sizeof(GetNotificationAttributesMsg);
bool error = false;
const bool complete = ancs_util_get_attr_ptrs(s_sms_ancs_data + header_len,
ARRAY_LENGTH(s_sms_ancs_data) - header_len,
s_fetched_notif_attributes,
NUM_FETCHED_NOTIF_ATTRIBUTES,
notif_attributes,
&error);
cl_assert(complete);
cl_assert(!error);
time_t timestamp = 0;
ANCSAppMetadata app_metadata = {0};
TimelineItem *item = ancs_item_create_and_populate(notif_attributes,
app_attrs,
&app_metadata,
NULL,
timestamp,
ANCSProperty_None);
cl_assert(item);
cl_assert_equal_i(item->action_group.num_actions, 1);
cl_assert_equal_i(item->action_group.actions[0].type, TimelineItemActionTypeAncsNegative);
}
void test_ancs_pebble_actions__test_group_sms(void) {
prv_support_sms_replies();
ANCSAttribute *notif_attributes[NUM_FETCHED_NOTIF_ATTRIBUTES] = {0};
ANCSAttribute *app_attrs[NUM_FETCHED_APP_ATTRIBUTES] = {0};
const size_t header_len = sizeof(GetNotificationAttributesMsg);
bool error = false;
const bool complete = ancs_util_get_attr_ptrs(s_group_sms_ancs_data + header_len,
ARRAY_LENGTH(s_group_sms_ancs_data) - header_len,
s_fetched_notif_attributes,
NUM_FETCHED_NOTIF_ATTRIBUTES,
notif_attributes,
&error);
cl_assert(complete);
cl_assert(!error);
time_t timestamp = 0;
ANCSAppMetadata app_metadata = {0};
const ANCSAttribute *app_id = notif_attributes[FetchedNotifAttributeIndexAppID];
iOSNotifPrefs *notif_prefs = ios_notif_pref_db_get_prefs(app_id->value, app_id->length);
TimelineItem *item = ancs_item_create_and_populate(notif_attributes,
app_attrs,
&app_metadata,
notif_prefs,
timestamp,
ANCSProperty_None);
cl_assert(item);
// We no longer show the reply action on group SMS messages (a less confusing UX)
// Before the phone would reject the message right away.
cl_assert_equal_i(item->action_group.num_actions, 1);
cl_assert_equal_i(item->action_group.actions[0].type, TimelineItemActionTypeAncsNegative);
}
// void test_ancs_pebble_actions__test_email(void) {
// ANCSAttribute *notif_attributes[NUM_FETCHED_NOTIF_ATTRIBUTES] = {0};
// ANCSAttribute *app_attrs[NUM_FETCHED_APP_ATTRIBUTES] = {0};
// const size_t header_len = sizeof(GetNotificationAttributesMsg);
// bool error = false;
// const bool complete = ancs_util_get_attr_ptrs(s_email_ancs_data + header_len,
// ARRAY_LENGTH(s_email_ancs_data) - header_len,
// s_fetched_notif_attributes,
// NUM_FETCHED_NOTIF_ATTRIBUTES,
// notif_attributes,
// &error);
// cl_assert(complete);
// cl_assert(!error);
// time_t timestamp = 0;
// ANCSAppMetadata app_metadata = {0};
// TimelineItem *item = ancs_item_create_and_populate(notif_attributes,
// app_attrs,
// &app_metadata,
// timestamp,
// ANCSProperty_None);
// cl_assert_equal_i(item->action_group.num_actions, 1);
// cl_assert_equal_i(item->action_group.actions[0].type, TimelineItemActionTypeAncsNegative);
// No e-mail actions yet
// TimelineItemAction *response_action = &item->action_group.actions[1];
// cl_assert_equal_i(response_action->type, TimelineItemActionTypeAncsResponse);
// cl_assert_equal_i(response_action->attr_list.num_attributes, 3);
// cl_assert_equal_i(response_action->attr_list.attributes[0].id, AttributeIdTitle);
// cl_assert_equal_s(response_action->attr_list.attributes[0].cstring, "Reply");
// cl_assert_equal_i(response_action->attr_list.attributes[1].id, AttributeIdSender);
// cl_assert_equal_s(response_action->attr_list.attributes[1].cstring, "Philip G");
// cl_assert_equal_i(response_action->attr_list.attributes[2].id, AttributeIdiOSAppIdentifier);
// cl_assert_equal_s(response_action->attr_list.attributes[2].cstring, "com.apple.MobileSMS");
// s_expected_send_data = s_email_action_data;
// timeline_invoke_action(item, response_action, &response_action->attr_list);
// cl_assert(s_sent_action);
// }
+123
View File
@@ -0,0 +1,123 @@
/*
* Copyright 2024 Google LLC
*
* 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.
*/
#include <stdint.h>
/**************** ANCS SMS ****************/
// 00 0c 00 00 00 06 00 00 07 05 00 43 6c 65 61 72 ........ ...Clear
// 00 13 00 63 6f 6d 2e 61 70 70 6c 65 2e 4d 6f 62 ...com.a pple.Mob
// 69 6c 65 53 4d 53 01 08 00 50 68 69 6c 69 70 20 ileSMS.. .Philip
// 47 02 00 00 03 12 00 43 61 6e 61 64 61 20 69 73 G......C anada is
// 20 74 68 65 20 62 65 73 74 05 0f 00 32 30 31 35 the bes t...2015
// 30 38 33 31 54 31 30 32 34 34 33 0831T102 443
static const uint8_t s_sms_ancs_data[] = {
0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x05, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72,
0x00, 0x13, 0x00, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x6f, 0x62,
0x69, 0x6c, 0x65, 0x53, 0x4d, 0x53, 0x01, 0x08, 0x00, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x20,
0x47, 0x02, 0x00, 0x00, 0x03, 0x12, 0x00, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x05, 0x0f, 0x00, 0x32, 0x30, 0x31, 0x35,
0x30, 0x38, 0x33, 0x31, 0x54, 0x31, 0x30, 0x32, 0x34, 0x34, 0x33
};
// 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
// 00 0c 06 0c 08 00 50 68 69 6c 69 70 20 47 01 08 ......Ph ilip G..
// 00 50 68 69 6c 69 70 20 47 03 12 00 43 61 6e 61 .Philip G...Cana
// 64 61 20 69 73 20 74 68 65 20 62 65 73 74 20 13 da is th e best .
// 00 63 6f 6d 2e 61 70 70 6c 65 2e 4d 6f 62 69 6c .com.app le.Mobil
// 65 53 4d 53 04 04 00 00 00 00 00 25 04 00 00 00 eSMS.... ...%....
// 00 00 ..
static const uint8_t s_sms_action_data[] = {
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x06, 0x0c, 0x08, 0x00, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x20, 0x47, 0x01, 0x08,
0x00, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x20, 0x47, 0x03, 0x12, 0x00, 0x43, 0x61, 0x6e, 0x61,
0x64, 0x61, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x13,
0x00, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x6f, 0x62, 0x69, 0x6c,
0x65, 0x53, 0x4d, 0x53, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00
};
/**************** Group SMS ****************/
// 00 0d 00 00 00 06 00 00 07 05 00 43 6c 65 61 72 ........ ...Clear
// 00 13 00 63 6f 6d 2e 61 70 70 6c 65 2e 4d 6f 62 ...com.a pple.Mob
// 69 6c 65 53 4d 53 01 10 00 62 6a 65 74 74 40 70 ileSMS.. .bjett@p
// 65 62 62 6c 65 2e 63 6f 6d 02 17 00 54 6f 20 79 ebble.co m...To y
// 6f 75 20 26 20 28 33 31 37 29 20 33 37 30 2d 32 ou & (31 7) 370-2
// 38 32 39 03 08 00 54 65 73 74 69 6e 67 20 05 0f 829...Te sting ..
// 00 32 30 31 35 30 39 30 32 54 31 36 31 39 32 32 .2015090 2T161922
static const uint8_t s_group_sms_ancs_data[] = {
0x00, 0x0d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x05, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72,
0x00, 0x13, 0x00, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x6f, 0x62,
0x69, 0x6c, 0x65, 0x53, 0x4d, 0x53, 0x01, 0x10, 0x00, 0x62, 0x6a, 0x65, 0x74, 0x74, 0x40, 0x70,
0x65, 0x62, 0x62, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x17, 0x00, 0x54, 0x6f, 0x20, 0x79,
0x6f, 0x75, 0x20, 0x26, 0x20, 0x28, 0x33, 0x31, 0x37, 0x29, 0x20, 0x33, 0x37, 0x30, 0x2d, 0x32,
0x38, 0x32, 0x39, 0x03, 0x08, 0x00, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x05, 0x0f,
0x00, 0x32, 0x30, 0x31, 0x35, 0x30, 0x39, 0x30, 0x32, 0x54, 0x31, 0x36, 0x31, 0x39, 0x32, 0x32
};
// 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
// 00 0d 05 01 05 00 52 65 70 6c 79 21 01 00 01 0c ......Reply!....
// 10 00 62 6a 65 74 74 40 70 65 62 62 6c 65 2e 63 [email protected]
// 6f 6d 20 13 00 63 6f 6d 2e 61 70 70 6c 65 2e 4d om ..com.apple.M
// 6f 62 69 6c 65 53 4d 53 02 17 00 54 6f 20 79 6f obileSMS...To yo
// 75 20 26 20 28 33 31 37 29 20 33 37 30 2d 32 38 u & (317) 370-28
// 32 39 29
static const uint8_t s_group_sms_action_data[] = {
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0d, 0x05, 0x01, 0x05, 0x00, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x21, 0x01, 0x00, 0x01, 0x0c,
0x10, 0x00, 0x62, 0x6a, 0x65, 0x74, 0x74, 0x40, 0x70, 0x65, 0x62, 0x62, 0x6c, 0x65, 0x2e, 0x63,
0x6f, 0x6d, 0x20, 0x13, 0x00, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x4d,
0x6f, 0x62, 0x69, 0x6c, 0x65, 0x53, 0x4d, 0x53, 0x02, 0x17, 0x00, 0x54, 0x6f, 0x20, 0x79, 0x6f,
0x75, 0x20, 0x26, 0x20, 0x28, 0x33, 0x31, 0x37, 0x29, 0x20, 0x33, 0x37, 0x30, 0x2d, 0x32, 0x38,
0x32, 0x39
};
/**************** Email ****************/
static const uint8_t s_email_ancs_data[] = {
0x00, 0x0d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x05, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72,
0x00, 0x14, 0x00, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x6f, 0x62,
0x69, 0x6c, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x01, 0x0e, 0x00, 0x50, 0x68, 0x69, 0x6c, 0x20, 0x47,
0x75, 0x6e, 0x6e, 0x65, 0x77, 0x69, 0x65, 0x6b, 0x02, 0x0b, 0x00, 0x54, 0x68, 0x65, 0x20, 0x53,
0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x03, 0x08, 0x00, 0x54, 0x68, 0x65, 0x20, 0x42, 0x6f, 0x64,
0x79, 0x05, 0x0f, 0x00, 0x32, 0x30, 0x31, 0x35, 0x30, 0x38, 0x33, 0x31, 0x54, 0x31, 0x31, 0x30,
0x33, 0x35, 0x39
};
/**************** Send Text ****************/
// 02 0f 71 aa ba 58 14 4b 5c 96 e2 c9 82 8c 97 34 ..q..X.K \......4
// cb 00 02 01 0e 00 59 6f 2c 20 77 68 61 74 27 73 ......Yo , what's
// 20 75 70 3f 0c 0c 00 35 35 35 2d 31 32 33 2d 34 up?...5 55-123-4
// 35 36 37 567
static const uint8_t s_send_text_data[] = {
0x02, 0x0f, 0x71, 0xaa, 0xba, 0x58, 0x14, 0x4b, 0x5c, 0x96, 0xe2, 0xc9, 0x82, 0x8c, 0x97, 0x34,
0xcb, 0x00, 0x02, 0x01, 0x0e, 0x00, 0x59, 0x6f, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x27, 0x73,
0x20, 0x75, 0x70, 0x3f, 0x0c, 0x0c, 0x00, 0x35, 0x35, 0x35, 0x2d, 0x31, 0x32, 0x33, 0x2d, 0x34,
0x35, 0x36, 0x37
};
/**************** PP SMS ****************/
// 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
// 00 00 01 01 0e 00 59 6f 2c 20 77 68 61 74 27 73 ......Yo , what's
// 20 75 70 3f up?
static const uint8_t s_sms_reply_action_data[] = {
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x0e, 0x00, 0x59, 0x6f, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x27, 0x73,
0x20, 0x75, 0x70, 0x3f
};
@@ -0,0 +1,130 @@
/*
* Copyright 2024 Google LLC
*
* 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.
*/
#include "clar.h"
#include "services/normal/timeline/timeline_actions.h"
// Test Data
///////////////////////////////////////////////////////////
#include "test_data.h"
static TimelineItemAction s_reply_action = {
.id = 0,
.type = TimelineItemActionTypeResponse,
.attr_list = (AttributeList) {
.num_attributes = 1,
.attributes = (Attribute[1]) {
{ .id = AttributeIdTitle, .cstring = "Reply" }
}
}
};
// Stubs
///////////////////////////////////////////////////////////
#include "stubs_common.h"
// Externs
///////////////////////////////////////////////////////////
extern const int TIMELINE_ACTION_ENDPOINT;
typedef struct ActionResultData ActionResultData;
extern ActionResultData *prv_invoke_action(ActionMenu *action_menu,
const TimelineItemAction *action,
const TimelineItem *pin, const char *label);
// Fakes / Helpers
///////////////////////////////////////////////////////////
static const uint8_t *s_expected_send_data = NULL;
static bool s_sent_action = false;
bool comm_session_send_data(CommSession *session, uint16_t endpoint_id,
const uint8_t* data, size_t length, uint32_t timeout_ms) {
if (s_expected_send_data == NULL) {
return false;
}
if (endpoint_id != TIMELINE_ACTION_ENDPOINT) {
return false;
}
cl_assert_equal_m(s_expected_send_data, data, length);
s_sent_action = true;
return true;
}
// Setup
/////////////////////////
void test_timeline_actions__initialize(void) {
s_expected_send_data = NULL;
s_sent_action = false;
}
void test_timeline_actions__cleanup(void) {
}
// Tests
///////////////////////////
// Tests a regular response to a notification
void test_timeline_actions__response(void) {
const TimelineItem item = {
.attr_list = (AttributeList) {
.num_attributes = 5,
.attributes = (Attribute[5]) {
{ .id = AttributeIdTitle, .cstring = "Ian Graham" },
{ .id = AttributeIdBody, .cstring = "this is a test notification" },
{ .id = AttributeIdIconTiny, .uint32 = TIMELINE_RESOURCE_GENERIC_SMS },
{ .id = AttributeIdBgColor, .uint8 = GColorIslamicGreenARGB8 }
}
},
.action_group = (TimelineItemActionGroup) {
.num_actions = 1,
.actions = &s_reply_action
}
};
s_expected_send_data = s_sms_reply_action_data;
prv_invoke_action(NULL, &item.action_group.actions[0], &item, "Yo, what's up?");
cl_assert(s_sent_action);
}
// Tests that we send the required data for the Send Text app and reply to call features
void test_timeline_actions__send_text(void) {
const TimelineItem item = {
.header = {
.id = UUID_SEND_SMS
},
.attr_list = (AttributeList) {
.num_attributes = 2,
.attributes = (Attribute[2]) {
{ .id = AttributeIdSender, .cstring = "555-123-4567" },
{ .id = AttributeIdiOSAppIdentifier, .cstring = "com.pebble.android.phone" }
}
},
.action_group = (TimelineItemActionGroup) {
.num_actions = 1,
.actions = &s_reply_action
}
};
s_expected_send_data = s_send_text_data;
prv_invoke_action(NULL, &item.action_group.actions[0], &item, "Yo, what's up?");
cl_assert(s_sent_action);
}
+49
View File
@@ -0,0 +1,49 @@
from waftools.pebble_test import clar
def build(ctx):
clar(ctx,
sources_ant_glob = \
"src/fw/comm/ble/kernel_le_client/ancs/ancs_util.c " \
"src/fw/flash_region/filesystem_regions.c " \
"src/fw/flash_region/flash_region.c " \
"src/fw/services/normal/blob_db/ios_notif_pref_db.c " \
"src/fw/services/normal/filesystem/flash_translation.c " \
"src/fw/services/normal/filesystem/pfs.c " \
"src/fw/services/normal/notifications/ancs/ancs_filtering.c " \
"src/fw/services/normal/notifications/ancs/ancs_item.c " \
"src/fw/services/normal/notifications/ancs/ancs_notifications.c " \
"src/fw/services/normal/notifications/ancs/ancs_notifications_util.c " \
"src/fw/services/normal/notifications/ancs/ancs_phone_call.c " \
"src/fw/services/normal/settings/settings_file.c " \
"src/fw/services/normal/settings/settings_raw_iter.c " \
"src/fw/services/normal/timeline/actions_endpoint.c " \
"src/fw/services/normal/timeline/attribute.c " \
"src/fw/services/normal/timeline/attribute_group.c " \
"src/fw/services/normal/timeline/attributes_actions.c " \
"src/fw/services/normal/timeline/item.c " \
"src/fw/services/normal/timeline/timeline.c " \
"src/fw/services/normal/timeline/timeline_actions.c " \
"src/fw/util/buffer.c " \
"src/fw/util/crc8.c " \
"src/fw/util/legacy_checksum.c " \
"src/fw/util/pstring.c " \
"src/fw/util/rand/rand.c " \
"src/fw/util/time/time.c "\
"src/fw/vendor/tinymt32/tinymt32.c " \
"tests/fakes/fake_spi_flash.c ",
test_sources_ant_glob = "test_ancs_pebble_actions.c",
override_includes=['dummy_board'])
clar(ctx,
sources_ant_glob =
"src/fw/services/normal/timeline/actions_endpoint.c " \
"src/fw/services/normal/timeline/attribute.c " \
"src/fw/services/normal/timeline/attribute_group.c " \
"src/fw/services/normal/timeline/attributes_actions.c " \
"src/fw/services/normal/timeline/item.c " \
"src/fw/services/normal/timeline/timeline.c " \
"src/fw/services/normal/timeline/timeline_actions.c " \
"src/fw/util/time/time.c ",
test_sources_ant_glob = "test_timeline_actions.c",
override_includes=['dummy_board'])
# vim:filetype=python