summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-02 16:44:22 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-02 16:44:22 +0000
commit09159e4aa8304fbee20969bebafb4084f77a22e4 (patch)
tree1baaf11d29bbd719debe25d639cbc0c16336db3e
parent660f781f6e03874a5f22014ada703ac3a77834d9 (diff)
parentacc6941aebdff5ac139e01aa60f24fb68656c39e (diff)
downloadPermission-09159e4aa8304fbee20969bebafb4084f77a22e4.tar.gz
Snap for 11397440 from acc6941aebdff5ac139e01aa60f24fb68656c39e to mainline-healthfitness-releaseaml_hef_341613000
Change-Id: I8b16fe2a5b4523fa26afebba6f78baa4592fea82
-rw-r--r--PermissionController/res/values-da/strings.xml4
-rw-r--r--PermissionController/res/values-ja/strings.xml8
-rw-r--r--PermissionController/res/values-ko/strings.xml2
-rw-r--r--PermissionController/res/values-pa-v33/strings.xml2
-rw-r--r--PermissionController/res/values-pa/strings.xml2
-rw-r--r--PermissionController/res/values-zu/strings.xml2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java25
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt178
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt10
-rw-r--r--tests/hostside/safetycenter/helper-app/Android.bp1
-rw-r--r--tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt36
-rw-r--r--tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt28
-rw-r--r--tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt99
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt2
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt2
18 files changed, 346 insertions, 105 deletions
diff --git a/PermissionController/res/values-da/strings.xml b/PermissionController/res/values-da/strings.xml
index a01f54f55..db2b515b5 100644
--- a/PermissionController/res/values-da/strings.xml
+++ b/PermissionController/res/values-da/strings.xml
@@ -352,10 +352,10 @@
<string name="role_assistant_label" msgid="4727586018198208128">"Standardapp for digital assistent"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"App for digital assistent"</string>
<string name="role_assistant_description" msgid="6622458130459922952">"Assistanceapps kan hjælpe dig på baggrund af oplysningerne på den aktuelle skærm. Nogle apps understøtter både startertjenester og tjenester til indtaling for at give dig integreret assistance."</string>
- <string name="role_browser_label" msgid="2877796144554070207">"Standardbrowserapp"</string>
+ <string name="role_browser_label" msgid="2877796144554070207">"Standardapp til browsing"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"Browserapp"</string>
<string name="role_browser_description" msgid="3465253637499842671">"Apps, der giver dig adgang til internettet og viser links, som du trykker på"</string>
- <string name="role_browser_request_title" msgid="2895200507835937192">"Vil du angive <xliff:g id="APP_NAME">%1$s</xliff:g> som din standardbrowserapp?"</string>
+ <string name="role_browser_request_title" msgid="2895200507835937192">"Vil du angive <xliff:g id="APP_NAME">%1$s</xliff:g> som din standardapp til browsing?"</string>
<string name="role_browser_request_description" msgid="5888803407905985941">"Der kræves ingen tilladelser"</string>
<string name="role_dialer_label" msgid="1100224146343237968">"Standardapp til opkald"</string>
<string name="role_dialer_short_label" msgid="7186888549465352489">"Opkaldsapp"</string>
diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml
index 7784829a1..9042b44d0 100644
--- a/PermissionController/res/values-ja/strings.xml
+++ b/PermissionController/res/values-ja/strings.xml
@@ -56,8 +56,8 @@
<string name="grant_dialog_button_keey_approximate_location" msgid="438025182769080011">"おおよその位置情報を保持"</string>
<string name="grant_dialog_button_allow_one_time" msgid="2618088516449706391">"今回のみ"</string>
<string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"常に許可"</string>
- <string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"すべてのファイルの管理を許可"</string>
- <string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"メディア ファイルへのアクセスを許可"</string>
+ <string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"すべての管理を許可"</string>
+ <string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"アクセスのみ許可"</string>
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"アプリ"</string>
<string name="app_permissions" msgid="3369917736607944781">"アプリの権限"</string>
<string name="unused_apps" msgid="2058057455175955094">"使用されていないアプリ"</string>
@@ -86,7 +86,7 @@
<string name="app_permissions_group_summary" msgid="8788419008958284002">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> 個のアプリを許可"</string>
<string name="app_permissions_group_summary2" msgid="4329922444840521150">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> 件のアプリを許可"</string>
<string name="menu_show_system" msgid="4254021607027872504">"システムアプリを表示"</string>
- <string name="menu_hide_system" msgid="3855390843744028465">"システムアプリを表示しない"</string>
+ <string name="menu_hide_system" msgid="3855390843744028465">"システムアプリを非表示"</string>
<string name="menu_show_7_days_data" msgid="8979611198508523706">"過去 7 日間を表示"</string>
<string name="menu_show_24_hours_data" msgid="8228054833323380780">"過去 24 時間を表示"</string>
<string name="manage_permission" msgid="2895385393037061964">"権限の管理"</string>
@@ -351,7 +351,7 @@
<string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"これらのアプリでは、画面、アクション、入力の表示、アクションの実行、ディスプレイの操作を行えます。"</string>
<string name="role_assistant_label" msgid="4727586018198208128">"デフォルトのデジタル アシスタント アプリ"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"デジタル アシスタント アプリ"</string>
- <string name="role_assistant_description" msgid="6622458130459922952">"アシストアプリは、表示している画面の情報に基づいてアシスタントを提供します。一部のアプリはランチャーと音声入力サービスの両方に対応しており、統合されたアシスタントを提供します。"</string>
+ <string name="role_assistant_description" msgid="6622458130459922952">"アシストアプリは、表示している画面の情報に基づいてサポートを提供します。一部のアプリはランチャーと音声入力サービスの両方に対応しており、統合されたサポートを提供します。"</string>
<string name="role_browser_label" msgid="2877796144554070207">"デフォルトのブラウザアプリ"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"ブラウザアプリ"</string>
<string name="role_browser_description" msgid="3465253637499842671">"インターネットにアクセスするためのアプリです。タップしたリンクは、このアプリで開きます。"</string>
diff --git a/PermissionController/res/values-ko/strings.xml b/PermissionController/res/values-ko/strings.xml
index 9ab5a5736..143fce74a 100644
--- a/PermissionController/res/values-ko/strings.xml
+++ b/PermissionController/res/values-ko/strings.xml
@@ -351,7 +351,7 @@
<string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"이 앱이 내 화면, 작업, 입력 내용을 보고 작업을 실행하며 디스플레이를 제어할 수 있습니다."</string>
<string name="role_assistant_label" msgid="4727586018198208128">"기본 디지털 어시스턴트 앱"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"디지털 어시스턴트 앱"</string>
- <string name="role_assistant_description" msgid="6622458130459922952">"지원 앱은 화면에 표시된 정보에 맞게 도움을 줄 수 있습니다. 일부 앱은 통합된 지원을 제공하기 위해 런처와 음성 입력 서비스를 모두 지원합니다."</string>
+ <string name="role_assistant_description" msgid="6622458130459922952">"지원 앱은 화면에 표시된 정보를 기반으로 도움을 줄 수 있습니다. 일부 앱은 통합된 지원을 제공하기 위해 런처와 음성 입력 서비스를 모두 지원합니다."</string>
<string name="role_browser_label" msgid="2877796144554070207">"기본 브라우저 앱"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"브라우저 앱"</string>
<string name="role_browser_description" msgid="3465253637499842671">"인터넷에 액세스하고 탭하는 링크를 표시하는 앱"</string>
diff --git a/PermissionController/res/values-pa-v33/strings.xml b/PermissionController/res/values-pa-v33/strings.xml
index 8f1b9a285..0aa143302 100644
--- a/PermissionController/res/values-pa-v33/strings.xml
+++ b/PermissionController/res/values-pa-v33/strings.xml
@@ -28,7 +28,7 @@
<string name="safety_center_entry_group_item_content_description" msgid="7348298582877249787">"ਸੂਚੀ ਆਈਟਮ। <xliff:g id="ENTRY_ITEM_TITLE">%1$s</xliff:g>. <xliff:g id="ENTRY_ITEM_SUMMARY">%2$s</xliff:g>"</string>
<string name="safety_center_entry_content_description" msgid="3639565652938224321">"<xliff:g id="ENTRY_ITEM_TITLE">%1$s</xliff:g>. <xliff:g id="ENTRY_ITEM_SUMMARY">%2$s</xliff:g>"</string>
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ਹੋਰ ਅਲਰਟ"</string>
- <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ਖਾਰਜ ਕੀਤੀਆਂ ਗਈਆਂ ਸੁਚੇਤਨਾਵਾਂ"</string>
+ <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ਖਾਰਜ ਕੀਤੇ ਅਲਰਟ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ਵਿਸਤਾਰ ਕਰੋ ਅਤੇ ਇੱਕ ਹੋਰ ਅਲਰਟ ਦੇਖੋ}one{ਵਿਸਤਾਰ ਕਰੋ ਅਤੇ # ਹੋਰ ਅਲਰਟ ਦੇਖੋ}other{ਵਿਸਤਾਰ ਕਰੋ ਅਤੇ # ਹੋਰ ਅਲਰਟ ਦੇਖੋ}}"</string>
<string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ਅਲਰਟ। <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"ਕਾਰਵਾਈ ਪੂਰੀ ਹੋਈ"</string>
diff --git a/PermissionController/res/values-pa/strings.xml b/PermissionController/res/values-pa/strings.xml
index 1c4539642..613f77c6e 100644
--- a/PermissionController/res/values-pa/strings.xml
+++ b/PermissionController/res/values-pa/strings.xml
@@ -371,7 +371,7 @@
<string name="role_sms_search_keywords" msgid="8022048144395047352">"ਲਿਖਤ ਸੁਨੇਹਾ, ਲਿਖਤ ਭੇਜਣਾ, ਸੁਨੇਹੇ, ਸੁਨੇਹਾ ਭੇਜਣਾ"</string>
<string name="role_emergency_label" msgid="7028825857206842366">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੰਕਟਕਾਲੀਨ ਐਪ"</string>
<string name="role_emergency_short_label" msgid="2388431453335350348">"ਸੰਕਟਕਾਲੀਨ ਐਪ"</string>
- <string name="role_emergency_description" msgid="5051840234887686630">"ਐਪਾਂ ਜੋ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀ ਡਾਕਟਰੀ ਜਾਣਕਾਰੀ ਰਿਕਾਰਡ ਕਰਨ ਅਤੇ ਇਸਨੂੰ ਸੰਕਟਕਾਲੀਨ ਮਦਦਗਾਰਾਂ ਤੱਕ ਪਹੁੰਚਯੋਗ ਬਣਾਉਣ ਦਿੰਦੀਆਂ ਹਨ; ਗੰਭੀਰ ਮੌਸਮੀ ਘਟਨਾਵਾਂ ਅਤੇ ਆਫ਼ਤਾਂ ਬਾਰੇ ਸੁਚੇਤਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦੀਆਂ ਹਨ; ਤੁਹਾਨੂੰ ਮਦਦ ਦੀ ਲੋੜ ਪੈਣ \'ਤੇ ਹੋਰਾਂ ਨੂੰ ਸੂਚਿਤ ਕਰਨ ਦਿੰਦੀਆਂ ਹਨ"</string>
+ <string name="role_emergency_description" msgid="5051840234887686630">"ਐਪਾਂ ਜੋ ਤੁਹਾਨੂੰ ਤੁਹਾਡੀ ਡਾਕਟਰੀ ਜਾਣਕਾਰੀ ਰਿਕਾਰਡ ਕਰਨ ਅਤੇ ਇਸਨੂੰ ਐਮਰਜੈਂਸੀ ਮਦਦਗਾਰਾਂ ਤੱਕ ਪਹੁੰਚਯੋਗ ਬਣਾਉਣ ਦਿੰਦੀਆਂ ਹਨ; ਬਹੁਤ ਜ਼ਿਆਦਾ ਖਰਾਬ ਮੌਸਮੀ ਘਟਨਾਵਾਂ ਅਤੇ ਆਫ਼ਤਾਂ ਬਾਰੇ ਅਲਰਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦਿੰਦੀਆਂ ਹਨ; ਤੁਹਾਨੂੰ ਮਦਦ ਦੀ ਲੋੜ ਪੈਣ \'ਤੇ ਹੋਰਾਂ ਨੂੰ ਸੂਚਿਤ ਕਰਨ ਦਿੰਦੀਆਂ ਹਨ"</string>
<string name="role_emergency_request_title" msgid="8469579020654348567">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੰਕਟਕਾਲੀਨ ਐਪ ਵਜੋਂ ਸੈੱਟ ਕਰਨਾ ਹੈ?"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"ਕਿਸੇ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ"</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"ice"</string>
diff --git a/PermissionController/res/values-zu/strings.xml b/PermissionController/res/values-zu/strings.xml
index b4f177a15..c90048a4e 100644
--- a/PermissionController/res/values-zu/strings.xml
+++ b/PermissionController/res/values-zu/strings.xml
@@ -198,7 +198,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Sebenzisa indawo eqondile"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Uma indawo ngqo ivaliwe, ama-app angakwazi ukufinyelela indawo yakho elinganiselwayo"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> imvume"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"<xliff:g id="PERM">%1$s</xliff:g> ukufinyelela kwale app"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"ukufinyelela kwale app ku<xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Bona zonke izimvume ze-<xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bona zonke izinhlelo zokusebenza ngale mvume"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Bonisa ukusetshenziswa kwe-microphone kamsizi"</string>
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index a6e521138..53f8fe712 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -66,7 +66,6 @@ import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
-import androidx.core.util.Consumer;
import androidx.core.util.Preconditions;
import com.android.modules.utils.build.SdkLevel;
@@ -417,7 +416,7 @@ public class GrantPermissionsActivity extends SettingsActivity
mViewModel.sendDirectlyToSettings(top, info.getGroupName());
return;
} else if (info.getOpenPhotoPicker()) {
- mViewModel.openPhotoPicker(top, GRANTED_USER_SELECTED);
+ mViewModel.openPhotoPicker(top);
return;
}
@@ -604,16 +603,14 @@ public class GrantPermissionsActivity extends SettingsActivity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- Consumer<Intent> callback = mViewModel.getActivityResultCallback();
- if (callback == null || (requestCode != APP_PERMISSION_REQUEST_CODE
- && requestCode != PHOTO_PICKER_REQUEST_CODE)) {
+ if (requestCode != APP_PERMISSION_REQUEST_CODE
+ && requestCode != PHOTO_PICKER_REQUEST_CODE) {
return;
}
if (requestCode == PHOTO_PICKER_REQUEST_CODE) {
data = new Intent("").putExtra(INTENT_PHOTOS_SELECTED, resultCode == RESULT_OK);
}
- callback.accept(data);
- mViewModel.setActivityResultCallback(null);
+ mViewModel.handleCallback(data, requestCode);
}
@Override
@@ -633,11 +630,10 @@ public class GrantPermissionsActivity extends SettingsActivity
mPreMergeShownGroupName = null;
}
- if (Objects.equals(READ_MEDIA_VISUAL, name)
- && result == GrantPermissionsViewHandler.GRANTED_USER_SELECTED) {
+ if (Objects.equals(READ_MEDIA_VISUAL, name) && result == GRANTED_USER_SELECTED) {
// Only the top activity can receive activity results
Activity top = mFollowerActivities.isEmpty() ? this : mFollowerActivities.get(0);
- mViewModel.openPhotoPicker(top, result);
+ mViewModel.openPhotoPicker(top);
logGrantPermissionActivityButtons(name, affectedForegroundPermissions, result);
return;
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
index 6bcf926d3..ba839ee0e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
@@ -35,6 +35,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import android.safetycenter.SafetyCenterManager;
import android.util.ArrayMap;
import android.view.Menu;
import android.view.MenuInflater;
@@ -93,6 +94,8 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
private static final int MENU_PERMISSION_USAGE = MENU_HIDE_SYSTEM + 1;
+ private static final String PRIVACY_CONTROLS_ACTION = "android.settings.PRIVACY_CONTROLS";
+
/**
* Create a bundle with the arguments needed by this fragment
*
@@ -281,12 +284,30 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
findPreference(ALLOWED_FOREGROUND.getCategoryName()).setVisible(false);
}
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getPrivacyControlsIntent() {
+ SafetyCenterManager safetyCenterManager =
+ getContext().getSystemService(SafetyCenterManager.class);
+ if (safetyCenterManager.isSafetyCenterEnabled()) {
+ return PRIVACY_CONTROLS_ACTION;
+ } else {
+ return Settings.ACTION_PRIVACY_SETTINGS;
+ }
+ }
+
@RequiresApi(Build.VERSION_CODES.S)
private CardViewPreference createSensorCard() {
boolean isLocation = Manifest.permission_group.LOCATION.equals(mPermGroupName);
Context context = getPreferenceManager().getContext();
- String action = isLocation ? Settings.ACTION_LOCATION_SOURCE_SETTINGS
- : Settings.ACTION_PRIVACY_SETTINGS;
+
+ String action;
+ if (isLocation) {
+ action = Settings.ACTION_LOCATION_SOURCE_SETTINGS;
+ } else if (SdkLevel.isAtLeastT()) {
+ action = getPrivacyControlsIntent();
+ } else {
+ action = Settings.ACTION_PRIVACY_SETTINGS;
+ }
CardViewPreference sensorCard = new CardViewPreference(context, action);
sensorCard.setKey(BLOCKED_SENSOR_PREF_KEY);
sensorCard.setIcon(Utils.getBlockedIcon(mPermGroupName));
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
index 3f19db475..d9fd7f2ea 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -186,6 +186,18 @@ class GrantPermissionsViewModel(
private var appPermGroupLiveDatas = mutableMapOf<String, LightAppPermGroupLiveData>()
+ internal data class ResultCallback(val consumer: Consumer<Intent>, val requestCode: Int)
+
+ private var activityResultCallback: ResultCallback? = null
+
+ init {
+ if (storedState?.containsKey(SAVED_REQUEST_CODE_KEY) == true) {
+ if (storedState.getInt(SAVED_REQUEST_CODE_KEY) == PHOTO_PICKER_REQUEST_CODE) {
+ setPhotoPickerCallback()
+ }
+ }
+ }
+
/**
* A class which represents a correctly requested permission group, and the buttons and messages
* which should be shown with it.
@@ -202,8 +214,6 @@ class GrantPermissionsViewModel(
val groupName = groupInfo.name
}
- var activityResultCallback: Consumer<Intent>? = null
-
/** A LiveData which holds a list of the currently pending RequestInfos */
val requestInfosLiveData =
object : SmartUpdateMediatorLiveData<List<RequestInfo>>() {
@@ -1494,7 +1504,9 @@ class GrantPermissionsViewModel(
Log.v(
LOG_TAG,
"Permission grant result requestId=$sessionId " +
- "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " +
+ "callingUid=${packageInfo.uid} " +
+ "callingPackage=$packageName " +
+ "permission=$permission " +
"isImplicit=$isImplicit result=$result " +
"isPermissionRationaleShown=$isPermissionRationaleShown"
)
@@ -1522,6 +1534,7 @@ class GrantPermissionsViewModel(
val (groupName, isBackground) = groupKey
outState.putInt(getInstanceStateKey(groupName, isBackground), groupState.state)
}
+ activityResultCallback?.let { outState.putInt(SAVED_REQUEST_CODE_KEY, it.requestCode) }
}
/**
@@ -1547,12 +1560,25 @@ class GrantPermissionsViewModel(
}
}
+ fun handleCallback(data: Intent?, requestCode: Int) {
+ val currCallback = activityResultCallback
+ if (currCallback == null || requestCode != currCallback.requestCode) {
+ return
+ }
+ currCallback.consumer.accept(data)
+ activityResultCallback = null
+ }
+
fun handleHealthConnectPermissions(activity: Activity) {
if (activityResultCallback == null) {
- activityResultCallback = Consumer {
- permGroupsToSkip.add(HEALTH_PERMISSION_GROUP)
- requestInfosLiveData.update()
- }
+ activityResultCallback =
+ ResultCallback(
+ {
+ permGroupsToSkip.add(HEALTH_PERMISSION_GROUP)
+ requestInfosLiveData.update()
+ },
+ APP_PERMISSION_REQUEST_CODE
+ )
val healthPermissions =
unfilteredAffectedPermissions
.filter { permission -> isHealthPermission(activity, permission) }
@@ -1575,55 +1601,72 @@ class GrantPermissionsViewModel(
*/
fun sendDirectlyToSettings(activity: Activity, groupName: String) {
if (activityResultCallback == null) {
- activityResultCallback = Consumer { data ->
- if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) {
- // User didn't interact, count against rate limit
- val group =
- groupStates[groupName to false]?.group
- ?: groupStates[groupName to true]?.group ?: return@Consumer
- if (group.background.isUserSet) {
- KotlinUtils.setGroupFlags(
- app,
- group,
- FLAG_PERMISSION_USER_FIXED to true,
- filterPermissions = group.backgroundPermNames
- )
- } else {
- KotlinUtils.setGroupFlags(
- app,
- group,
- FLAG_PERMISSION_USER_SET to true,
- filterPermissions = group.backgroundPermNames
- )
- }
- }
+ activityResultCallback =
+ ResultCallback(
+ Consumer { data ->
+ if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) {
+ // User didn't interact, count against rate limit
+ val group =
+ groupStates[groupName to false]?.group
+ ?: groupStates[groupName to true]?.group
+ ?: return@Consumer
+ if (group.background.isUserSet) {
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_USER_FIXED to true,
+ filterPermissions = group.backgroundPermNames
+ )
+ } else {
+ KotlinUtils.setGroupFlags(
+ app,
+ group,
+ FLAG_PERMISSION_USER_SET to true,
+ filterPermissions = group.backgroundPermNames
+ )
+ }
+ }
- permGroupsToSkip.add(groupName)
- // Update our liveData now that there is a new skipped group
- requestInfosLiveData.update()
- }
+ permGroupsToSkip.add(groupName)
+ // Update our liveData now that there is a new skipped group
+ requestInfosLiveData.update()
+ },
+ APP_PERMISSION_REQUEST_CODE
+ )
startAppPermissionFragment(activity, groupName)
}
}
- fun openPhotoPicker(activity: Activity, result: Int) {
+ fun openPhotoPicker(activity: Activity) {
if (activityResultCallback != null) {
return
}
if (groupStates[READ_MEDIA_VISUAL to false]?.affectedPermissions == null) {
return
}
- activityResultCallback = Consumer { data ->
- val anySelected = data?.getBooleanExtra(INTENT_PHOTOS_SELECTED, true) == true
- if (anySelected) {
- onPermissionGrantResult(READ_MEDIA_VISUAL, null, result)
- } else {
- onPermissionGrantResult(READ_MEDIA_VISUAL, null, CANCELED)
- }
- requestInfosLiveData.update()
- }
- openPhotoPickerForApp(activity, packageInfo.uid, unfilteredAffectedPermissions,
- PHOTO_PICKER_REQUEST_CODE)
+ setPhotoPickerCallback()
+ openPhotoPickerForApp(
+ activity,
+ packageInfo.uid,
+ unfilteredAffectedPermissions,
+ PHOTO_PICKER_REQUEST_CODE
+ )
+ }
+
+ private fun setPhotoPickerCallback() {
+ activityResultCallback =
+ ResultCallback(
+ { data ->
+ val anySelected = data?.getBooleanExtra(INTENT_PHOTOS_SELECTED, true) == true
+ if (anySelected) {
+ onPermissionGrantResult(READ_MEDIA_VISUAL, null, GRANTED_USER_SELECTED)
+ } else {
+ onPermissionGrantResult(READ_MEDIA_VISUAL, null, CANCELED)
+ }
+ requestInfosLiveData.update()
+ },
+ PHOTO_PICKER_REQUEST_CODE
+ )
}
/**
@@ -1634,15 +1677,19 @@ class GrantPermissionsViewModel(
*/
fun sendToSettingsFromLink(activity: Activity, groupName: String) {
startAppPermissionFragment(activity, groupName)
- activityResultCallback = Consumer { data ->
- val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
- if (returnGroupName != null) {
- permGroupsToSkip.add(returnGroupName)
- val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, -1)
- logSettingsInteraction(returnGroupName, result)
- requestInfosLiveData.update()
- }
- }
+ activityResultCallback =
+ ResultCallback(
+ { data ->
+ val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
+ if (returnGroupName != null) {
+ permGroupsToSkip.add(returnGroupName)
+ val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, -1)
+ logSettingsInteraction(returnGroupName, result)
+ requestInfosLiveData.update()
+ }
+ },
+ APP_PERMISSION_REQUEST_CODE
+ )
}
/**
@@ -1662,15 +1709,19 @@ class GrantPermissionsViewModel(
putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
putExtra(Constants.EXTRA_SESSION_ID, sessionId)
}
- activityResultCallback = Consumer { data ->
- val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
- if (returnGroupName != null) {
- permGroupsToSkip.add(returnGroupName)
- val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, CANCELED)
- logSettingsInteraction(returnGroupName, result)
- requestInfosLiveData.update()
- }
- }
+ activityResultCallback =
+ ResultCallback(
+ { data ->
+ val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
+ if (returnGroupName != null) {
+ permGroupsToSkip.add(returnGroupName)
+ val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, CANCELED)
+ logSettingsInteraction(returnGroupName, result)
+ requestInfosLiveData.update()
+ }
+ },
+ APP_PERMISSION_REQUEST_CODE
+ )
activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
}
@@ -1836,6 +1887,7 @@ class GrantPermissionsViewModel(
companion object {
const val APP_PERMISSION_REQUEST_CODE = 1
const val PHOTO_PICKER_REQUEST_CODE = 2
+ const val SAVED_REQUEST_CODE_KEY = "saved_request_code"
private const val STATE_UNKNOWN = 0
private const val STATE_ALLOWED = 1
private const val STATE_DENIED = 2
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index f2aa0ae66..59906283a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -144,9 +144,6 @@ object KotlinUtils {
/** Whether to show the location indicators. */
private const val PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled"
- /** Whether location accuracy feature is enabled */
- private const val PROPERTY_LOCATION_ACCURACY_ENABLED = "location_accuracy_enabled"
-
/** Whether to show 7-day toggle in privacy hub. */
private const val PRIVACY_DASHBOARD_7_DAY_TOGGLE = "privacy_dashboard_7_day_toggle"
@@ -252,12 +249,7 @@ object KotlinUtils {
/** Whether the location accuracy feature is enabled */
@ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
fun isLocationAccuracyEnabled(): Boolean {
- return SdkLevel.isAtLeastS() &&
- DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_LOCATION_ACCURACY_ENABLED,
- true
- )
+ return SdkLevel.isAtLeastS()
}
/** Default state of location precision true: default is FINE. false: default is COARSE. */
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
index 6f146e48c..9feecf5d4 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
@@ -92,7 +92,7 @@ abstract class SafetyCenterFragment : PreferenceFragmentCompat() {
}
val safetyCenterIntent: ParsedSafetyCenterIntent =
- requireActivity().getIntent().toSafetyCenterIntent()
+ requireActivity().intent.toSafetyCenterIntent()
val isQsFragment =
getArguments()?.getBoolean(QUICK_SETTINGS_SAFETY_CENTER_FRAGMENT, false) ?: false
collapsableIssuesCardHelper =
@@ -120,7 +120,7 @@ abstract class SafetyCenterFragment : PreferenceFragmentCompat() {
override fun onStart() {
super.onStart()
configureInteractionLogger()
- safetyCenterViewModel.interactionLogger.record(Action.SAFETY_CENTER_VIEWED)
+ logSafetyCenterViewedEvent()
}
override fun onResume() {
@@ -162,6 +162,26 @@ abstract class SafetyCenterFragment : PreferenceFragmentCompat() {
abstract fun configureInteractionLogger()
+ private fun logSafetyCenterViewedEvent() {
+ // If Safety Center was opened due to an associated notification click (i.e. intent has an
+ // associated issue), record that issue's metadata on the SAFETY_CENTER_VIEWED event
+ val maybeIssueKey = requireActivity().intent.toSafetyCenterIntent().safetyCenterIssueKey
+ val maybeIssue =
+ maybeIssueKey?.let {
+ safetyCenterViewModel.getCurrentSafetyCenterDataAsUiData().getMatchingIssue(it)
+ }
+
+ if (maybeIssue == null) {
+ safetyCenterViewModel.interactionLogger.record(Action.SAFETY_CENTER_VIEWED)
+ } else {
+ safetyCenterViewModel.interactionLogger.recordForIssue(
+ Action.SAFETY_CENTER_VIEWED,
+ maybeIssue,
+ isDismissed = false
+ )
+ }
+ }
+
private fun displayErrorDetails(errorDetails: SafetyCenterErrorDetails?) {
if (errorDetails == null) return
Toast.makeText(requireContext(), errorDetails.errorMessage, Toast.LENGTH_LONG).show()
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
index 239f9a377..69a315f08 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
@@ -16,6 +16,7 @@
package com.android.permissioncontroller.safetycenter.ui.model
+import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntryGroup
@@ -24,12 +25,21 @@ import android.safetycenter.SafetyCenterIssue
import android.safetycenter.SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK
import androidx.annotation.RequiresApi
import com.android.safetycenter.internaldata.SafetyCenterBundles.ISSUES_TO_GROUPS_BUNDLE_KEY
+import com.android.safetycenter.internaldata.SafetyCenterIds
+import com.android.safetycenter.internaldata.SafetyCenterIssueKey
/** UI model representation of Safety Center Data */
data class SafetyCenterUiData(
val safetyCenterData: SafetyCenterData,
val resolvedIssues: Map<IssueId, ActionId> = emptyMap()
) {
+ @RequiresApi(TIRAMISU)
+ fun getMatchingIssue(issueKey: SafetyCenterIssueKey): SafetyCenterIssue? {
+ return safetyCenterData.issues.find {
+ SafetyCenterIds.issueIdFromString(it.id).safetyCenterIssueKey == issueKey
+ }
+ }
+
/** Returns the [SafetyCenterEntryGroup] corresponding to the provided ID */
@RequiresApi(UPSIDE_DOWN_CAKE)
fun getMatchingGroup(groupId: String): SafetyCenterEntryGroup? {
diff --git a/tests/hostside/safetycenter/helper-app/Android.bp b/tests/hostside/safetycenter/helper-app/Android.bp
index cf4372d99..a05f8d2f3 100644
--- a/tests/hostside/safetycenter/helper-app/Android.bp
+++ b/tests/hostside/safetycenter/helper-app/Android.bp
@@ -30,6 +30,7 @@ android_test_helper_app {
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
+ "safety-center-pending-intents",
"safety-center-test-util-lib",
],
} \ No newline at end of file
diff --git a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt
index 784701b8a..f37479180 100644
--- a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt
+++ b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt
@@ -19,14 +19,21 @@ package android.safetycenter.hostside.device
import android.content.Context
import android.os.Bundle
import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID
+import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID
+import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
+import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterQsActivity
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.openPageAndExit
import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestHelper
import com.android.safetycenter.testing.SafetyCenterTestRule
+import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.SafetySourceTestData.Companion.INFORMATION_ISSUE_ID
+import com.android.safetycenter.testing.UiTestHelper.waitAllTextDisplayed
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -47,6 +54,7 @@ class SafetyCenterInteractionLoggingHelperTests {
private val context: Context = ApplicationProvider.getApplicationContext()
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
+ private val safetySourceTestData = SafetySourceTestData(context)
@get:Rule val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
@@ -61,6 +69,34 @@ class SafetyCenterInteractionLoggingHelperTests {
}
@Test
+ fun openSafetyCenterFullFromQs() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
+
+ context.launchSafetyCenterQsActivity {
+ openPageAndExit("Settings") { waitAllTextDisplayed(safetySourceTestData.informationIssue.title) }
+ }
+ }
+
+ @Test
+ fun openSafetyCenterWithIssueIntent() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
+
+ val extras = Bundle()
+ extras.putString(EXTRA_SAFETY_SOURCE_ID, SINGLE_SOURCE_ID)
+ extras.putString(EXTRA_SAFETY_SOURCE_ISSUE_ID, INFORMATION_ISSUE_ID)
+
+ context.launchSafetyCenterActivity(extras) {}
+ }
+
+ @Test
+ fun openSafetyCenterQs() {
+ context.launchSafetyCenterQsActivity {}
+ }
+
+ @Test
fun openSubpageFromIntentExtra() {
val config = safetyCenterTestConfigs.singleSourceConfig
safetyCenterTestHelper.setConfig(config)
diff --git a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt
index 458516379..dc3cb3fc2 100644
--- a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt
+++ b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt
@@ -21,12 +21,16 @@ import android.safetycenter.SafetySourceData
import android.safetycenter.SafetySourceIssue
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.safetycenter.pendingintents.PendingIntentSender
+import com.android.safetycenter.testing.SafetyCenterActivityLauncher
import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestHelper
import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.StatusBarNotificationWithChannel
+import com.android.safetycenter.testing.TestNotificationListener
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -49,7 +53,9 @@ class SafetyCenterNotificationLoggingHelperTests {
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
- @get:Rule val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule
+ val safetyCenterTestRule =
+ SafetyCenterTestRule(safetyCenterTestHelper, withNotifications = true)
@Before
fun setUp() {
@@ -64,6 +70,13 @@ class SafetyCenterNotificationLoggingHelperTests {
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, newTestDataWithNotifiableIssue())
}
+ @Test
+ fun openSafetyCenterFromNotification() {
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, newTestDataWithNotifiableIssue())
+
+ sendContentPendingIntent(TestNotificationListener.waitForSingleNotification())
+ }
+
private fun newTestDataWithNotifiableIssue(): SafetySourceData =
safetySourceTestData
.defaultCriticalDataBuilder()
@@ -74,4 +87,17 @@ class SafetyCenterNotificationLoggingHelperTests {
.build()
)
.build()
+
+ companion object {
+ private fun sendContentPendingIntent(
+ statusBarNotificationWithChannel: StatusBarNotificationWithChannel
+ ) {
+ val contentIntent =
+ statusBarNotificationWithChannel.statusBarNotification.notification.contentIntent
+ SafetyCenterActivityLauncher.executeBlockAndExit(
+ launchActivity = { PendingIntentSender.send(contentIntent) },
+ block = {} // No action required
+ )
+ }
+ }
}
diff --git a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt
index 5fe9e0a2a..91222d045 100644
--- a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt
+++ b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt
@@ -24,10 +24,13 @@ import com.android.compatibility.common.util.ApiLevelUtil
import com.android.os.AtomsProto.Atom
import com.android.os.AtomsProto.SafetyCenterInteractionReported
import com.android.os.AtomsProto.SafetyCenterInteractionReported.Action
+import com.android.os.AtomsProto.SafetyCenterInteractionReported.NavigationSource
import com.android.os.AtomsProto.SafetyCenterInteractionReported.ViewType
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
import com.google.common.truth.Truth.assertThat
+import java.math.BigInteger
+import java.security.MessageDigest
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
@@ -67,15 +70,76 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
- assertThat(safetyCenterViewedAtoms).isNotEmpty()
+ assertThat(safetyCenterViewedAtoms).hasSize(1)
+ with(safetyCenterViewedAtoms.first()) {
+ assertThat(navigationSource).isEqualTo(NavigationSource.SOURCE_UNKNOWN)
+ assertThat(viewType).isEqualTo(ViewType.FULL)
+ }
}
@Test
- fun sendNotification_recordsNotificationPostedEvent() {
+ fun openSafetyCenterQs_recordsSafetyCenterViewedEvent() {
+ helperAppRule.runTest(TEST_CLASS_NAME, "openSafetyCenterQs")
+
+ val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
+
+ assertThat(safetyCenterViewedAtoms).hasSize(1)
+ with(safetyCenterViewedAtoms.first()) {
+ assertThat(navigationSource).isEqualTo(NavigationSource.QUICK_SETTINGS_TILE)
+ assertThat(viewType).isEqualTo(ViewType.QUICK_SETTINGS)
+ }
+ }
+
+ @Test
+ fun openSafetyCenterFullFromQs_recordsViewEventWithCorrectSource() {
+ helperAppRule.runTest(TEST_CLASS_NAME, "openSafetyCenterFullFromQs")
+
+ val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
+
+ val viewTypesToNavSources =
+ safetyCenterViewedAtoms.associate { Pair(it.viewType, it.navigationSource) }
+ assertThat(viewTypesToNavSources)
+ .containsEntry(ViewType.FULL, NavigationSource.QUICK_SETTINGS_TILE)
+ }
+
+ @Test
+ fun openSafetyCenterWithIssueIntent_recordsViewEventWithAssociatedIssueMetadata() {
+ helperAppRule.runTest(TEST_CLASS_NAME, testMethodName = "openSafetyCenterWithIssueIntent")
+
+ val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
+
+ assertThat(safetyCenterViewedAtoms).hasSize(1)
+ with(safetyCenterViewedAtoms.first()) {
+ assertThat(navigationSource).isEqualTo(NavigationSource.NOTIFICATION)
+ assertThat(encodedSafetySourceId).isEqualTo(ENCODED_SINGLE_SOURCE_ID)
+ assertThat(encodedIssueTypeId).isEqualTo(ENCODED_ISSUE_TYPE_ID)
+ }
+ }
+
+ @Test
+ fun openSafetyCenterWithNotification_recordsViewEventWithAssociatedIssueMetadata() {
assumeAtLeastUpsideDownCake("Safety Center notification APIs require Android U+")
helperAppRule.runTest(
testClassName = ".SafetyCenterNotificationLoggingHelperTests",
+ testMethodName = "openSafetyCenterFromNotification"
+ )
+
+ val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
+
+ assertThat(safetyCenterViewedAtoms).hasSize(1)
+ with(safetyCenterViewedAtoms.first()) {
+ assertThat(navigationSource).isEqualTo(NavigationSource.NOTIFICATION)
+ assertThat(encodedSafetySourceId).isEqualTo(ENCODED_SINGLE_SOURCE_ID)
+ assertThat(encodedIssueTypeId).isEqualTo(ENCODED_ISSUE_TYPE_ID)
+ }
+ }
+
+ @Test
+ fun sendNotification_recordsNotificationPostedEvent() {
+ assumeAtLeastUpsideDownCake("Safety Center notification APIs require Android U+")
+ helperAppRule.runTest(
+ testClassName = ".SafetyCenterNotificationLoggingHelperTests",
testMethodName = "sendNotification"
)
@@ -97,8 +161,7 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
assertThat(safetyCenterViewedAtoms).hasSize(1)
with(safetyCenterViewedAtoms.first()) {
assertThat(viewType).isEqualTo(ViewType.SUBPAGE)
- assertThat(navigationSource)
- .isEqualTo(SafetyCenterInteractionReported.NavigationSource.SOURCE_UNKNOWN)
+ assertThat(navigationSource).isEqualTo(NavigationSource.SOURCE_UNKNOWN)
assertThat(sessionId).isNotNull()
}
}
@@ -113,8 +176,7 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
val subpageViewedEvent = safetyCenterViewedAtoms.find { it.viewType == ViewType.SUBPAGE }
assertThat(subpageViewedEvent).isNotNull()
- assertThat(subpageViewedEvent!!.navigationSource)
- .isEqualTo(SafetyCenterInteractionReported.NavigationSource.SAFETY_CENTER)
+ assertThat(subpageViewedEvent!!.navigationSource).isEqualTo(NavigationSource.SAFETY_CENTER)
assertThat(safetyCenterViewedAtoms.map { it.sessionId }.distinct()).hasSize(1)
}
@@ -129,8 +191,7 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
assertThat(safetyCenterViewedAtoms).hasSize(1)
with(safetyCenterViewedAtoms.first()) {
assertThat(viewType).isEqualTo(ViewType.SUBPAGE)
- assertThat(navigationSource)
- .isEqualTo(SafetyCenterInteractionReported.NavigationSource.SETTINGS)
+ assertThat(navigationSource).isEqualTo(NavigationSource.SETTINGS)
assertThat(sessionId).isNotNull()
}
}
@@ -148,5 +209,27 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
private companion object {
const val TEST_CLASS_NAME = ".SafetyCenterInteractionLoggingHelperTests"
+
+ // LINT.IfChange(single_source_id)
+ val ENCODED_SINGLE_SOURCE_ID = encodeId("test_single_source_id")
+ // LINT.ThenChange(/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt:issue_type_id)
+
+ // LINT.IfChange(issue_type_id)
+ val ENCODED_ISSUE_TYPE_ID = encodeId("issue_type_id")
+ // LINT.ThenChange(/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt:issue_type_id)
+
+ /**
+ * Encodes a string into an long ID. The ID is a SHA-256 of the string, truncated to 64
+ * bits.
+ */
+ fun encodeId(id: String?): Long {
+ if (id == null) return 0
+
+ val digest = MessageDigest.getInstance("MD5")
+ digest.update(id.toByteArray())
+
+ // Truncate to the size of a long
+ return BigInteger(digest.digest()).toLong()
+ }
}
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
index 2af2b391a..b0d209fcc 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
@@ -856,7 +856,9 @@ class SafetyCenterTestConfigs(private val context: Context) {
* ID of the only source provided in [singleSourceConfig], [severityZeroConfig] and
* [noPageOpenConfig].
*/
+ // LINT.IfChange(single_source_id)
const val SINGLE_SOURCE_ID = "test_single_source_id"
+ // LINT.ThenChange(/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt:single_source_id)
/** ID of the only source provided in [singleSourceAllProfileConfig]. */
const val SINGLE_SOURCE_ALL_PROFILE_ID = "test_single_source_all_profile_id"
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
index 2c4f856bb..66be55fa8 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
@@ -802,7 +802,9 @@ class SafetySourceTestData(private val context: Context) {
const val CRITICAL_ISSUE_ACTION_ID = "critical_issue_action_id"
/** Issue type ID for all the issues in this file */
+ // LINT.IfChange(issue_type_id)
const val ISSUE_TYPE_ID = "issue_type_id"
+ // LINT.ThenChange(/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt:issue_type_id)
const val CONFIRMATION_TITLE = "Confirmation title"
const val CONFIRMATION_TEXT = "Confirmation text"