Merge "Fix issues in RTL." into rvc-dev
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index bd811fc..a954f36 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1200,8 +1200,10 @@
}
if (mDeferredDestroySurfaceControl != null) {
- mTmpTransaction.remove(mDeferredDestroySurfaceControl).apply();
- mDeferredDestroySurfaceControl = null;
+ synchronized (mSurfaceControlLock) {
+ mTmpTransaction.remove(mDeferredDestroySurfaceControl).apply();
+ mDeferredDestroySurfaceControl = null;
+ }
}
runOnUiThread(this::performDrawFinished);
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index b387a68..68943bf 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -75,7 +75,10 @@
/** @hide */
public static AutofillId withoutSession(@NonNull AutofillId id) {
final int flags = id.mFlags & ~FLAG_HAS_SESSION;
- return new AutofillId(flags, id.mViewId, id.mVirtualLongId, NO_SESSION);
+ final long virtualChildId =
+ ((id.mFlags & FLAG_IS_VIRTUAL_LONG) != 0) ? id.mVirtualLongId
+ : id.mVirtualIntId;
+ return new AutofillId(flags, id.mViewId, virtualChildId, NO_SESSION);
}
/** @hide */
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 65872f4..afeceb7 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1309,7 +1309,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Εντοπίστηκε αναλογικό αξεσουάρ ήχου"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Η συνδεδεμένη συσκευή δεν είναι συμβατή με αυτό το τηλέφωνο. Πατήστε για να μάθετε περισσότερα."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
- <string name="adb_active_notification_message" msgid="5617264033476778211">"Απενεργοποιήστε τον εντοπισμό/διόρθ. σφαλμάτων USB"</string>
+ <string name="adb_active_notification_message" msgid="5617264033476778211">"Πατήστε για απενεργοποίηση εντοπισμού/διόρθ. σφαλμάτων USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"Επιλογή για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"Συνδέθηκε ο ασύρματος εντοπισμός σφαλμάτων"</string>
<string name="adbwifi_active_notification_message" msgid="930987922852867972">"Πατήστε, για να απενεργοποιήσετε τον ασύρματο εντοπισμό σφαλμάτων"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 36380b8..31abd82 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -202,10 +202,8 @@
<string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string>
<string name="personal_apps_suspension_title" msgid="7561416677884286600">"Turn on your work profile"</string>
<string name="personal_apps_suspension_text" msgid="6115455688932935597">"Your personal apps are blocked until you turn on your work profile"</string>
- <!-- no translation found for personal_apps_suspension_soon_text (8123898693479590) -->
- <skip />
- <!-- no translation found for personal_apps_suspended_turn_profile_on (2758012869627513689) -->
- <skip />
+ <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Personal apps will be blocked on <xliff:g id="DATE">%1$s</xliff:g> at <xliff:g id="TIME">%2$s</xliff:g>. Your IT admin doesn’t allow your work profile to stay off for more than <xliff:g id="NUMBER">%3$d</xliff:g> days."</string>
+ <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Turn on"</string>
<string name="me" msgid="6207584824693813140">"Me"</string>
<string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tablet options"</string>
<string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV options"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 91a8d05..bb06173 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -2032,7 +2032,7 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item>
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ficheiro</item>
</plurals>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Non hai persoas recomendadas coas que compartir contido"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Non hai recomendacións de persoas coas que compartir contido"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de aplicacións"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Esta aplicación non está autorizada a realizar gravacións, pero pode capturar audio a través deste dispositivo USB."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Inicio"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 3fe0766..5161fdc 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1230,7 +1230,7 @@
<string name="volume_unknown" msgid="4041914008166576293">"កម្រិតសំឡេង"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"កម្រិតសំឡេងប៊្លូធូស"</string>
<string name="volume_icon_description_ringer" msgid="2187800636867423459">"កម្រិតសំឡេងរោទ៍"</string>
- <string name="volume_icon_description_incall" msgid="4491255105381227919">"កម្រិតសំឡេងហៅ"</string>
+ <string name="volume_icon_description_incall" msgid="4491255105381227919">"កម្រិតសំឡេងហៅទូរសព្ទ"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"កម្រិតសំឡេងមេឌៀ"</string>
<string name="volume_icon_description_notification" msgid="579091344110747279">"កម្រិតសំឡេងការជូនដំណឹង"</string>
<string name="ringtone_default" msgid="9118299121288174597">"សំឡេងរោទ៍លំនាំដើម"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index bc896d6..25aa3b5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1308,7 +1308,7 @@
<string name="usb_power_notification_message" msgid="7284765627437897702">"ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ. ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"ಅನ್ಲಾಗ್ ಆಡಿಯೋ ಪರಿಕರ ಪತ್ತೆಯಾಗಿದೆ"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"ಲಗತ್ತಿಸಲಾದ ಸಾಧನವು ಈ ಫೋನಿನೊಂದಿಗೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="adb_active_notification_title" msgid="408390247354560331">"USB ಡೀಬಗಿಂಗ್ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
+ <string name="adb_active_notification_title" msgid="408390247354560331">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="adb_active_notification_message" product="tv" msgid="6624498401272780855">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಆಯ್ಕೆ ಮಾಡಿ."</string>
<string name="adbwifi_active_notification_title" msgid="6147343659168302473">"ವೈರ್ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -2032,7 +2032,7 @@
<item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್ಗಳು</item>
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್ಗಳು</item>
</plurals>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ಹಂಚಿಕೊಳ್ಳಲು, ಯಾವುದೇ ಶಿಫಾರಸು ಮಾಡಲಾದ ಜನರಿಲ್ಲ"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"ಹಂಚಿಕೊಳ್ಳಲು ಶಿಫಾರಸು ಮಾಡಲಾದವರು ಯಾರೂ ಇಲ್ಲ"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"ಆ್ಯಪ್ಗಳ ಪಟ್ಟಿ"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"ಈ ಆ್ಯಪ್ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಲ್ಲದು."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"ಹೋಮ್"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a7e6f99..a5a0f9e 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -2032,7 +2032,7 @@
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फाइल</item>
<item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> फाइल</item>
</plurals>
- <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"शेअर करण्यासाठी कोणतीही शिफारस केलेले लोक नाहीत"</string>
+ <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"शेअर करण्यासाठी शिफारस केलेल्या कोणत्याही व्यक्ती नाहीत"</string>
<string name="chooser_all_apps_button_label" msgid="3230427756238666328">"अॅप्स सूची"</string>
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"या अॅपला रेकॉर्ड करण्याची परवानगी दिली गेली नाही पण हे USB डिव्हाइस वापरून ऑडिओ कॅप्चर केला जाऊ शकतो."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"होम"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index cc8137c..64302da 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1912,7 +1912,7 @@
<string name="demo_starting_message" msgid="6577581216125805905">"Demo starten…"</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"Apparaat resetten…"</string>
<string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> uitgeschakeld"</string>
- <string name="conference_call" msgid="5731633152336490471">"Telefonische vergadering"</string>
+ <string name="conference_call" msgid="5731633152336490471">"Conferencecall"</string>
<string name="tooltip_popup_title" msgid="7863719020269945722">"Knopinfo"</string>
<string name="app_category_game" msgid="4534216074910244790">"Games"</string>
<string name="app_category_audio" msgid="8296029904794676222">"Muziek en audio"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index f803f02..4becdaa 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -60,7 +60,7 @@
<string name="ClirMmi" msgid="4702929460236547156">"ଆଉଟଗୋଇଙ୍ଗ୍ କଲର୍ ଆଇଡି"</string>
<string name="ColpMmi" msgid="4736462893284419302">"ସଂଯୁକ୍ତ ଲାଇନ୍ ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"ସଂଯୁକ୍ତ ଲାଇନ୍ ID କଟକଣା"</string>
- <string name="CfMmi" msgid="8390012691099787178">"କଲ୍ ଫରୱାର୍ଡିଙ୍ଗ"</string>
+ <string name="CfMmi" msgid="8390012691099787178">"କଲ୍ ଫରୱାର୍ଡିଂ"</string>
<string name="CwMmi" msgid="3164609577675404761">"କଲ୍ ଅପେକ୍ଷାରତ"</string>
<string name="BaMmi" msgid="7205614070543372167">"କଲ୍ ବ୍ୟାରିଙ୍ଗ୍"</string>
<string name="PwdMmi" msgid="3360991257288638281">"ପାସ୍ୱର୍ଡ ପରିବର୍ତ୍ତନ"</string>
@@ -88,7 +88,7 @@
<string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"ଜରୁରୀକାଳୀନ କଲ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="EmergencyCallWarningSummary" msgid="1194185880092805497">"ୱାଇ-ଫାଇ ସାହାଯ୍ୟରେ ଜରୁରୀକାଳୀନ କଲ୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
<string name="notification_channel_network_alert" msgid="4788053066033851841">"ଆଲର୍ଟ"</string>
- <string name="notification_channel_call_forward" msgid="8230490317314272406">"କଲ୍ ଫରୱାର୍ଡିଙ୍ଗ"</string>
+ <string name="notification_channel_call_forward" msgid="8230490317314272406">"କଲ୍ ଫରୱାର୍ଡିଂ"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"ଜରୁରୀକାଳୀନ କଲବ୍ୟାକ୍ ମୋଡ୍"</string>
<string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"ମୋବାଇଲ୍ ଡାଟା ଷ୍ଟାଟସ୍"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"SMS ମେସେଜ୍"</string>
diff --git a/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java b/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
index a8ca6f0..b329e55 100644
--- a/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
+++ b/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
@@ -126,6 +126,32 @@
}
@Test
+ public void testVirtual_Long_withoutSession() {
+ final AutofillId id = new AutofillId(new AutofillId(42), 108L, 666);
+ final AutofillId idWithoutSession = AutofillId.withoutSession(id);
+ assertThat(idWithoutSession.getViewId()).isEqualTo(42);
+ assertThat(idWithoutSession.isVirtualLong()).isTrue();
+ assertThat(idWithoutSession.isVirtualInt()).isFalse();
+ assertThat(idWithoutSession.isNonVirtual()).isFalse();
+ assertThat(idWithoutSession.getVirtualChildLongId()).isEqualTo(108L);
+ assertThat(idWithoutSession.getVirtualChildIntId()).isEqualTo(View.NO_ID);
+ assertThat(idWithoutSession.getSessionId()).isEqualTo(NO_SESSION);
+ }
+
+ @Test
+ public void testVirtual_Int_withoutSession() {
+ final AutofillId id = new AutofillId(42, 108);
+ final AutofillId idWithoutSession = AutofillId.withoutSession(id);
+ assertThat(idWithoutSession.getViewId()).isEqualTo(42);
+ assertThat(idWithoutSession.isVirtualLong()).isFalse();
+ assertThat(idWithoutSession.isVirtualInt()).isTrue();
+ assertThat(idWithoutSession.isNonVirtual()).isFalse();
+ assertThat(idWithoutSession.getVirtualChildIntId()).isEqualTo(108);
+ assertThat(idWithoutSession.getVirtualChildLongId()).isEqualTo(View.NO_ID);
+ assertThat(idWithoutSession.getSessionId()).isEqualTo(NO_SESSION);
+ }
+
+ @Test
public void testSetResetSession() {
final AutofillId id = new AutofillId(42);
assertNonVirtual(id, 42, NO_SESSION);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index 10e9137..2a40b76 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -58,16 +58,14 @@
override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
bouncerOrRun {
- val effect = if (!isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect
- vibrate(effect)
+ cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
cvh.action(BooleanAction(templateId, !isChecked))
}
}
override fun touch(cvh: ControlViewHolder, templateId: String, control: Control) {
- vibrate(Vibrations.toggleOnEffect)
-
bouncerOrRun {
+ cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
if (cvh.usePanel()) {
showDialog(cvh, control.getAppIntent().getIntent())
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index 1f0ca9b..0ec4cc5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -231,9 +231,11 @@
rangeAnimator?.cancel()
if (isDragging) {
- clipLayer.level = newLevel
val isEdge = newLevel == MIN_LEVEL || newLevel == MAX_LEVEL
- cvh.controlActionCoordinator.drag(isEdge)
+ if (clipLayer.level != newLevel) {
+ cvh.controlActionCoordinator.drag(isEdge)
+ clipLayer.level = newLevel
+ }
} else if (newLevel != clipLayer.level) {
rangeAnimator = ValueAnimator.ofInt(cvh.clipLayer.level, newLevel).apply {
addUpdateListener {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt
index c0f6aab..29b7e985 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/Vibrations.kt
@@ -20,35 +20,9 @@
import android.os.VibrationEffect.Composition.PRIMITIVE_TICK
object Vibrations {
- private const val TOGGLE_TICK_COUNT = 40
-
- val toggleOnEffect = initToggleOnEffect()
- val toggleOffEffect = initToggleOffEffect()
val rangeEdgeEffect = initRangeEdgeEffect()
val rangeMiddleEffect = initRangeMiddleEffect()
- private fun initToggleOnEffect(): VibrationEffect {
- val composition = VibrationEffect.startComposition()
- composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 200)
- var i = 0
- while (i++ < TOGGLE_TICK_COUNT) {
- composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 0)
- }
- composition.addPrimitive(PRIMITIVE_TICK, 0.5f, 100)
- return composition.compose()
- }
-
- private fun initToggleOffEffect(): VibrationEffect {
- val composition = VibrationEffect.startComposition()
- composition.addPrimitive(PRIMITIVE_TICK, 0.5f, 0)
- composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 100)
- var i = 0
- while (i++ < TOGGLE_TICK_COUNT) {
- composition.addPrimitive(PRIMITIVE_TICK, 0.05f, 0)
- }
- return composition.compose()
- }
-
private fun initRangeEdgeEffect(): VibrationEffect {
val composition = VibrationEffect.startComposition()
composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
index 9dcc187..87612f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
@@ -52,7 +52,7 @@
private NotificationGuts mGutsContainer;
private OnClickListener mOnOk = v -> {
- closeControls(v);
+ mGutsContainer.closeControls(v, false);
};
public AppOpsInfo(Context context, AttributeSet attrs) {
@@ -117,6 +117,7 @@
});
TextView ok = findViewById(R.id.ok);
ok.setOnClickListener(mOnOk);
+ ok.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
}
private String getPrompt() {
@@ -160,19 +161,6 @@
}
}
- private void closeControls(View v) {
- mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, false, false);
- }
-
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;
@@ -200,6 +188,7 @@
@Override
public boolean handleCloseControls(boolean save, boolean force) {
+ mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index f7ad50e..94e12e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1122,9 +1122,8 @@
}
public void setGutsView(MenuItem item) {
- if (mGuts != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
- ((NotificationGuts.GutsContent) item.getGutsView()).setGutsParent(mGuts);
- mGuts.setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
+ if (getGuts() != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
+ getGuts().setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 2e7b175..daa4ffe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -137,13 +137,13 @@
mSelectedAction = ACTION_HOME;
mShortcutManager.requestPinShortcut(mShortcutInfo, null);
mShadeController.animateCollapsePanels();
- closeControls(v, true);
+ mGutsContainer.closeControls(v, true);
};
private OnClickListener mOnSnoozeClick = v -> {
mSelectedAction = ACTION_SNOOZE;
mOnSnoozeClickListener.onClick(v, 1);
- closeControls(v, true);
+ mGutsContainer.closeControls(v, true);
};
*/
@@ -164,7 +164,7 @@
private OnClickListener mOnDone = v -> {
mPressedApply = true;
- closeControls(v, true);
+ mGutsContainer.closeControls(v, true);
};
public NotificationConversationInfo(Context context, AttributeSet attrs) {
@@ -258,6 +258,7 @@
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDone);
+ done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
}
private void bindActions() {
@@ -543,25 +544,6 @@
controller.show();
}
- /**
- * Closes the controls and commits the updated importance values (indirectly).
- *
- * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
- * user does not have the ability to undo the action anymore.
- */
- @VisibleForTesting
- void closeControls(View v, boolean save) {
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, save, false /* force */);
- }
-
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index c762b73..eeac46a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -22,12 +22,14 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
@@ -59,6 +61,31 @@
private GutsContent mGutsContent;
+ private View.AccessibilityDelegate mGutsContentAccessibilityDelegate =
+ new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(
+ View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+ }
+
+ @Override
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ if (super.performAccessibilityAction(host, action, args)) {
+ return true;
+ }
+
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_LONG_CLICK:
+ closeControls(host, false);
+ return true;
+ }
+
+ return false;
+ }
+ };
+
public interface GutsContent {
public void setGutsParent(NotificationGuts listener);
@@ -110,6 +137,11 @@
* view on the lockscreen
*/
boolean needsFalsingProtection();
+
+ /**
+ * Equivalent to {@link View#setAccessibilityDelegate(AccessibilityDelegate)}
+ */
+ void setAccessibilityDelegate(AccessibilityDelegate gutsContentAccessibilityDelegate);
}
public interface OnGutsClosedListener {
@@ -146,6 +178,8 @@
}
public void setGutsContent(GutsContent content) {
+ content.setGutsParent(this);
+ content.setAccessibilityDelegate(mGutsContentAccessibilityDelegate);
mGutsContent = content;
removeAllViews();
addView(mGutsContent.getContentView());
@@ -237,13 +271,29 @@
/**
* Closes any exposed guts/views.
+ */
+ public void closeControls(View eventSource, boolean save) {
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ getLocationOnScreen(parentLoc);
+ eventSource.getLocationOnScreen(targetLoc);
+ final int centerX = eventSource.getWidth() / 2;
+ final int centerY = eventSource.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+
+ closeControls(x, y, save, false);
+ }
+
+ /**
+ * Closes any exposed guts/views.
*
* @param x x coordinate to animate the close circular reveal with
* @param y y coordinate to animate the close circular reveal with
* @param save whether the state should be saved
* @param force whether the guts should be force-closed regardless of state.
*/
- public void closeControls(int x, int y, boolean save, boolean force) {
+ private void closeControls(int x, int y, boolean save, boolean force) {
// First try to dismiss any blocking helper.
boolean wasBlockingHelperDismissed =
Dependency.get(NotificationBlockingHelperManager.class)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index f434fbb..a131ebe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -141,7 +141,7 @@
// used by standard ui
private OnClickListener mOnDismissSettings = v -> {
mPressedApply = true;
- closeControls(v, true);
+ mGutsContainer.closeControls(v, true);
};
public NotificationInfo(Context context, AttributeSet attrs) {
@@ -250,7 +250,7 @@
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDismissSettings);
-
+ done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
View silent = findViewById(R.id.silence);
View alert = findViewById(R.id.alert);
@@ -330,7 +330,7 @@
mUniqueChannelsInRow, mPkgIcon, mOnSettingsClickListener);
mChannelEditorDialogController.setOnFinishListener(() -> {
mPresentingChannelEditorDialog = false;
- closeControls(this, false);
+ mGutsContainer.closeControls(this, false);
});
mChannelEditorDialogController.show();
}
@@ -528,25 +528,6 @@
return intent;
}
- /**
- * Closes the controls and commits the updated importance values (indirectly).
- *
- * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
- * user does not have the ability to undo the action anymore.
- */
- @VisibleForTesting
- void closeControls(View v, boolean save) {
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, save, false /* force */);
- }
-
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
index cde3dfd..1ffb244 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
@@ -380,16 +380,8 @@
private void undoSnooze(View v) {
mSelectedOption = null;
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
showSnoozeOptions(false);
- mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
+ mGutsContainer.closeControls(v, false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
index eb28c58..84bc181 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
@@ -89,7 +89,7 @@
private OnClickListener mOnDone = v -> {
mPressedApply = true;
- closeControls(v, true);
+ mGutsContainer.closeControls(v, true);
};
public PartialConversationInfo(Context context, AttributeSet attrs) {
@@ -132,6 +132,7 @@
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDone);
+ done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
}
private void bindActions() {
@@ -172,7 +173,7 @@
mUniqueChannelsInRow, mPkgIcon, mOnSettingsClickListener);
mChannelEditorDialogController.setOnFinishListener(() -> {
mPresentingChannelEditorDialog = false;
- closeControls(this, false);
+ mGutsContainer.closeControls(this, false);
});
mChannelEditorDialogController.show();
}
@@ -317,25 +318,6 @@
}
}
- /**
- * Closes the controls and commits the updated importance values (indirectly).
- *
- * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
- * user does not have the ability to undo the action anymore.
- */
- @VisibleForTesting
- void closeControls(View v, boolean save) {
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- mGutsContainer.closeControls(x, y, save, false /* force */);
- }
-
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
index dd5cb58..ec73a75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
@@ -144,7 +144,7 @@
final View okButton = mAppOpsInfo.findViewById(R.id.ok);
okButton.performClick();
assertEquals(1, latch.getCount());
- verify(mGutsParent, times(1)).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mGutsParent, times(1)).closeControls(eq(okButton), anyBoolean());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index b39de34..b1f67ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -173,7 +173,7 @@
doAnswer((Answer<Object>) invocation -> {
mNotificationInfo.handleCloseControls(true, false);
return null;
- }).when(mNotificationGuts).closeControls(anyInt(), anyInt(), eq(true), eq(false));
+ }).when(mNotificationGuts).closeControls(any(View.class), eq(true));
// Our view is never attached to a window so the View#post methods in NotificationInfo never
// get called. Setting this will skip the post and do the action immediately.
mNotificationInfo.mSkipPost = true;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index e066d99..a153d41 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -1894,6 +1894,8 @@
return runWaveform();
} else if ("prebaked".equals(cmd)) {
return runPrebaked();
+ } else if ("capabilities".equals(cmd)) {
+ return runCapabilities();
} else if ("cancel".equals(cmd)) {
cancelVibrate(mToken);
return 0;
@@ -2016,10 +2018,15 @@
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runPrebaked");
try {
CommonOptions commonOptions = new CommonOptions();
+ boolean shouldFallback = false;
String opt;
while ((opt = getNextOption()) != null) {
- commonOptions.check(opt);
+ if ("-b".equals(opt)) {
+ shouldFallback = true;
+ } else {
+ commonOptions.check(opt);
+ }
}
if (checkDoNotDisturb(commonOptions)) {
@@ -2033,8 +2040,7 @@
description = "Shell command";
}
- VibrationEffect effect =
- VibrationEffect.get(id, false);
+ VibrationEffect effect = VibrationEffect.get(id, shouldFallback);
VibrationAttributes attrs = createVibrationAttributes(commonOptions);
vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command",
mToken);
@@ -2044,12 +2050,39 @@
}
}
+ private int runCapabilities() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runCapabilities");
+ try (PrintWriter pw = getOutPrintWriter();) {
+ pw.println("Vibrator capabilities:");
+ if (hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+ pw.println(" Always on effects");
+ }
+ if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+ pw.println(" Compose effects");
+ }
+ if (mSupportsAmplitudeControl || hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
+ pw.println(" Amplitude control");
+ }
+ if (mSupportsExternalControl || hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
+ pw.println(" External control");
+ }
+ if (hasCapability(IVibrator.CAP_EXTERNAL_AMPLITUDE_CONTROL)) {
+ pw.println(" External amplitude control");
+ }
+ pw.println("");
+ return 0;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
+ }
+
private VibrationAttributes createVibrationAttributes(CommonOptions commonOptions) {
final int flags = commonOptions.force
? VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY
: 0;
return new VibrationAttributes.Builder()
- .setUsage(VibrationAttributes.USAGE_UNKNOWN)
+ // Used to apply Settings.System.HAPTIC_FEEDBACK_INTENSITY to scale effects.
+ .setUsage(VibrationAttributes.USAGE_TOUCH)
.replaceFlags(flags)
.build();
}
@@ -2062,19 +2095,26 @@
pw.println(" Prints this help text.");
pw.println("");
pw.println(" vibrate duration [description]");
- pw.println(" Vibrates for duration milliseconds; ignored when device is on DND ");
- pw.println(" (Do Not Disturb) mode.");
+ pw.println(" Vibrates for duration milliseconds; ignored when device is on ");
+ pw.println(" DND (Do Not Disturb) mode; touch feedback strength user setting ");
+ pw.println(" will be used to scale amplitude.");
pw.println(" waveform [-d description] [-r index] [-a] duration [amplitude] ...");
- pw.println(" Vibrates for durations and amplitudes in list;");
- pw.println(" ignored when device is on DND (Do Not Disturb) mode.");
+ pw.println(" Vibrates for durations and amplitudes in list; ignored when ");
+ pw.println(" device is on DND (Do Not Disturb) mode; touch feedback strength ");
+ pw.println(" user setting will be used to scale amplitude.");
pw.println(" If -r is provided, the waveform loops back to the specified");
pw.println(" index (e.g. 0 loops from the beginning)");
pw.println(" If -a is provided, the command accepts duration-amplitude pairs;");
pw.println(" otherwise, it accepts durations only and alternates off/on");
pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255.");
- pw.println(" prebaked effect-id [description]");
+ pw.println(" prebaked [-b] effect-id [description]");
pw.println(" Vibrates with prebaked effect; ignored when device is on DND ");
- pw.println(" (Do Not Disturb) mode.");
+ pw.println(" (Do Not Disturb) mode; touch feedback strength user setting ");
+ pw.println(" will be used to scale amplitude.");
+ pw.println(" If -b is provided, the prebaked fallback effect will be played if");
+ pw.println(" the device doesn't support the given effect-id.");
+ pw.println(" capabilities");
+ pw.println(" Prints capabilities of this device.");
pw.println(" cancel");
pw.println(" Cancels any active vibration");
pw.println("Common Options:");
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 9476e92..5f63233 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -77,6 +77,7 @@
import android.util.SparseArray;
import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -114,7 +115,7 @@
private static final String TAG = "UriGrantsManagerService";
// Maximum number of persisted Uri grants a package is allowed
private static final int MAX_PERSISTED_URI_GRANTS = 128;
- private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false;
+ private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true;
private final Object mLock = new Object();
private final H mH;
@@ -122,6 +123,7 @@
PackageManagerInternal mPmInternal;
/** File storing persisted {@link #mGrantedUriPermissions}. */
+ @GuardedBy("mLock")
private final AtomicFile mGrantFile;
/** XML constants used in {@link #mGrantFile} */
@@ -142,6 +144,7 @@
* This optimized lookup structure maps from {@link UriPermission#targetUid}
* to {@link UriPermission#uri} to {@link UriPermission}.
*/
+ @GuardedBy("mLock")
private final SparseArray<ArrayMap<GrantUri, UriPermission>>
mGrantedUriPermissions = new SparseArray<>();
@@ -206,39 +209,44 @@
}
}
+ @Override
+ public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
+ Uri uri, final int modeFlags, int sourceUserId, int targetUserId) {
+ grantUriPermissionFromOwnerUnlocked(token, fromUid, targetPkg, uri, modeFlags, sourceUserId,
+ targetUserId);
+ }
+
/**
* @param uri This uri must NOT contain an embedded userId.
* @param sourceUserId The userId in which the uri is to be resolved.
* @param targetUserId The userId of the app that receives the grant.
*/
- @Override
- public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
- final int modeFlags, int sourceUserId, int targetUserId) {
+ private void grantUriPermissionFromOwnerUnlocked(IBinder token, int fromUid, String targetPkg,
+ Uri uri, final int modeFlags, int sourceUserId, int targetUserId) {
targetUserId = mAmInternal.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), targetUserId, false, ALLOW_FULL_ONLY,
"grantUriPermissionFromOwner", null);
- synchronized(mLock) {
- UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
- if (owner == null) {
- throw new IllegalArgumentException("Unknown owner: " + token);
- }
- if (fromUid != Binder.getCallingUid()) {
- if (Binder.getCallingUid() != myUid()) {
- // Only system code can grant URI permissions on behalf
- // of other users.
- throw new SecurityException("nice try");
- }
- }
- if (targetPkg == null) {
- throw new IllegalArgumentException("null target");
- }
- if (uri == null) {
- throw new IllegalArgumentException("null uri");
- }
- grantUriPermission(fromUid, targetPkg, new GrantUri(sourceUserId, uri, modeFlags),
- modeFlags, owner, targetUserId);
+ UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+ if (owner == null) {
+ throw new IllegalArgumentException("Unknown owner: " + token);
}
+ if (fromUid != Binder.getCallingUid()) {
+ if (Binder.getCallingUid() != myUid()) {
+ // Only system code can grant URI permissions on behalf
+ // of other users.
+ throw new SecurityException("nice try");
+ }
+ }
+ if (targetPkg == null) {
+ throw new IllegalArgumentException("null target");
+ }
+ if (uri == null) {
+ throw new IllegalArgumentException("null uri");
+ }
+
+ grantUriPermissionUnlocked(fromUid, targetPkg, new GrantUri(sourceUserId, uri, modeFlags),
+ modeFlags, owner, targetUserId);
}
@Override
@@ -362,7 +370,7 @@
persistChanged |= prefixPerm.takePersistableModes(modeFlags);
}
- persistChanged |= maybePrunePersistedUriGrants(uid);
+ persistChanged |= maybePrunePersistedUriGrantsLocked(uid);
if (persistChanged) {
schedulePersistUriGrants();
@@ -374,8 +382,8 @@
public void clearGrantedUriPermissions(String packageName, int userId) {
mAmInternal.enforceCallingPermission(
CLEAR_APP_GRANTED_URI_PERMISSIONS, "clearGrantedUriPermissions");
- synchronized(mLock) {
- removeUriPermissionsForPackage(packageName, userId, true, true);
+ synchronized (mLock) {
+ removeUriPermissionsForPackageLocked(packageName, userId, true, true);
}
}
@@ -416,11 +424,11 @@
if (exactPerm != null) {
persistChanged |= exactPerm.releasePersistableModes(modeFlags);
- removeUriPermissionIfNeeded(exactPerm);
+ removeUriPermissionIfNeededLocked(exactPerm);
}
if (prefixPerm != null) {
persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
- removeUriPermissionIfNeeded(prefixPerm);
+ removeUriPermissionIfNeededLocked(prefixPerm);
}
if (persistChanged) {
@@ -441,8 +449,9 @@
* @param targetOnly When {@code true}, only remove permissions where the app is the target,
* not source.
*/
- void removeUriPermissionsForPackage(
- String packageName, int userHandle, boolean persistable, boolean targetOnly) {
+ @GuardedBy("mLock")
+ private void removeUriPermissionsForPackageLocked(String packageName, int userHandle,
+ boolean persistable, boolean targetOnly) {
if (userHandle == UserHandle.USER_ALL && packageName == null) {
throw new IllegalArgumentException("Must narrow by either package or user");
}
@@ -494,7 +503,9 @@
}
/** Returns if the ContentProvider has granted a uri to callingUid */
- boolean checkAuthorityGrants(int callingUid, ProviderInfo cpi, int userId, boolean checkUser) {
+ @GuardedBy("mLock")
+ private boolean checkAuthorityGrantsLocked(int callingUid, ProviderInfo cpi, int userId,
+ boolean checkUser) {
final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
if (perms != null) {
for (int i = perms.size() - 1; i >= 0; i--) {
@@ -530,7 +541,8 @@
*
* @return if any mutations occured that require persisting.
*/
- private boolean maybePrunePersistedUriGrants(int uid) {
+ @GuardedBy("mLock")
+ private boolean maybePrunePersistedUriGrantsLocked(int uid) {
final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
if (perms == null) return false;
if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
@@ -552,14 +564,14 @@
if (DEBUG) Slog.v(TAG, "Trimming grant created at " + perm.persistedCreateTime);
perm.releasePersistableModes(~0);
- removeUriPermissionIfNeeded(perm);
+ removeUriPermissionIfNeededLocked(perm);
}
return true;
}
/** Like checkGrantUriPermission, but takes an Intent. */
- NeededUriGrants checkGrantUriPermissionFromIntent(int callingUid,
+ private NeededUriGrants checkGrantUriPermissionFromIntentUnlocked(int callingUid,
String targetPkg, Intent intent, int mode, NeededUriGrants needed, int targetUserId) {
if (DEBUG) Slog.v(TAG,
"Checking URI perm to data=" + (intent != null ? intent.getData() : null)
@@ -598,7 +610,8 @@
}
if (data != null) {
GrantUri grantUri = GrantUri.resolve(contentUserHint, data, mode);
- targetUid = checkGrantUriPermission(callingUid, targetPkg, grantUri, mode, targetUid);
+ targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg, grantUri, mode,
+ targetUid);
if (targetUid > 0) {
if (needed == null) {
needed = new NeededUriGrants(targetPkg, targetUid, mode);
@@ -611,7 +624,7 @@
Uri uri = clip.getItemAt(i).getUri();
if (uri != null) {
GrantUri grantUri = GrantUri.resolve(contentUserHint, uri, mode);
- targetUid = checkGrantUriPermission(callingUid, targetPkg,
+ targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg,
grantUri, mode, targetUid);
if (targetUid > 0) {
if (needed == null) {
@@ -622,7 +635,7 @@
} else {
Intent clipIntent = clip.getItemAt(i).getIntent();
if (clipIntent != null) {
- NeededUriGrants newNeeded = checkGrantUriPermissionFromIntent(
+ NeededUriGrants newNeeded = checkGrantUriPermissionFromIntentUnlocked(
callingUid, targetPkg, clipIntent, mode, needed, targetUserId);
if (newNeeded != null) {
needed = newNeeded;
@@ -635,7 +648,8 @@
return needed;
}
- void readGrantedUriPermissions() {
+ @GuardedBy("mLock")
+ private void readGrantedUriPermissionsLocked() {
if (DEBUG) Slog.v(TAG, "readGrantedUriPermissions()");
final long now = System.currentTimeMillis();
@@ -681,7 +695,7 @@
if (targetUid != -1) {
final GrantUri grantUri = new GrantUri(sourceUserId, uri,
prefix ? Intent.FLAG_GRANT_PREFIX_URI_PERMISSION : 0);
- final UriPermission perm = findOrCreateUriPermission(
+ final UriPermission perm = findOrCreateUriPermissionLocked(
sourcePkg, targetPkg, targetUid, grantUri);
perm.initPersistedModes(modeFlags, createdTime);
}
@@ -703,7 +717,8 @@
}
}
- private UriPermission findOrCreateUriPermission(String sourcePkg,
+ @GuardedBy("mLock")
+ private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
String targetPkg, int targetUid, GrantUri grantUri) {
ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris == null) {
@@ -740,15 +755,18 @@
return;
}
- final UriPermission perm = findOrCreateUriPermission(
- pi.packageName, targetPkg, targetUid, grantUri);
+ final UriPermission perm;
+ synchronized (mLock) {
+ perm = findOrCreateUriPermissionLocked(pi.packageName, targetPkg, targetUid, grantUri);
+ }
perm.grantModes(modeFlags, owner);
mPmInternal.grantImplicitAccess(UserHandle.getUserId(targetUid), null,
UserHandle.getAppId(targetUid), pi.applicationInfo.uid, false /*direct*/);
}
/** Like grantUriPermissionUnchecked, but takes an Intent. */
- void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed, UriPermissionOwner owner) {
+ private void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed,
+ UriPermissionOwner owner) {
if (needed == null) {
return;
}
@@ -759,7 +777,7 @@
}
}
- void grantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+ private void grantUriPermissionUnlocked(int callingUid, String targetPkg, GrantUri grantUri,
final int modeFlags, UriPermissionOwner owner, int targetUserId) {
if (targetPkg == null) {
throw new NullPointerException("targetPkg");
@@ -767,7 +785,8 @@
int targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
targetUserId);
- targetUid = checkGrantUriPermission(callingUid, targetPkg, grantUri, modeFlags, targetUid);
+ targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg, grantUri, modeFlags,
+ targetUid);
if (targetUid < 0) {
return;
}
@@ -775,7 +794,7 @@
grantUriPermissionUnchecked(targetUid, targetPkg, grantUri, modeFlags, owner);
}
- void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
+ private void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
final int modeFlags) {
if (DEBUG) Slog.v(TAG, "Revoking all granted permissions to " + grantUri);
@@ -788,8 +807,19 @@
return;
}
+ final boolean callerHoldsPermissions = checkHoldingPermissionsUnlocked(pi, grantUri,
+ callingUid, modeFlags);
+ synchronized (mLock) {
+ revokeUriPermissionLocked(targetPackage, callingUid, grantUri, modeFlags,
+ callerHoldsPermissions);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void revokeUriPermissionLocked(String targetPackage, int callingUid, GrantUri grantUri,
+ final int modeFlags, final boolean callerHoldsPermissions) {
// Does the caller have this permission on the URI?
- if (!checkHoldingPermissions(pi, grantUri, callingUid, modeFlags)) {
+ if (!callerHoldsPermissions) {
// If they don't have direct access to the URI, then revoke any
// ownerless URI permissions that have been granted to them.
final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
@@ -861,7 +891,7 @@
* the given {@link ProviderInfo}. Final permission checking is always done
* in {@link ContentProvider}.
*/
- private boolean checkHoldingPermissions(
+ private boolean checkHoldingPermissionsUnlocked(
ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
if (DEBUG) Slog.v(TAG, "checkHoldingPermissions: uri=" + grantUri + " uid=" + uid);
if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
@@ -870,11 +900,17 @@
return false;
}
}
- return checkHoldingPermissionsInternal(pi, grantUri, uid, modeFlags, true);
+ return checkHoldingPermissionsInternalUnlocked(pi, grantUri, uid, modeFlags, true);
}
- private boolean checkHoldingPermissionsInternal(ProviderInfo pi,
+ private boolean checkHoldingPermissionsInternalUnlocked(ProviderInfo pi,
GrantUri grantUri, int uid, final int modeFlags, boolean considerUidPermissions) {
+ // We must never hold our local mLock in this method, since we may need
+ // to call into ActivityManager for dynamic permission checks
+ if (Thread.holdsLock(mLock)) {
+ throw new IllegalStateException("Must never hold local mLock");
+ }
+
if (pi.applicationInfo.uid == uid) {
return true;
} else if (!pi.exported) {
@@ -968,7 +1004,8 @@
return readMet && writeMet && forceMet;
}
- private void removeUriPermissionIfNeeded(UriPermission perm) {
+ @GuardedBy("mLock")
+ private void removeUriPermissionIfNeededLocked(UriPermission perm) {
if (perm.modeFlags != 0) {
return;
}
@@ -985,6 +1022,7 @@
}
}
+ @GuardedBy("mLock")
private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris != null) {
@@ -1020,7 +1058,7 @@
* If you already know the uid of the target, you can supply it in
* lastTargetUid else set that to -1.
*/
- int checkGrantUriPermission(int callingUid, String targetPkg, GrantUri grantUri,
+ private int checkGrantUriPermissionUnlocked(int callingUid, String targetPkg, GrantUri grantUri,
int modeFlags, int lastTargetUid) {
if (!Intent.isAccessUriMode(modeFlags)) {
return -1;
@@ -1076,7 +1114,7 @@
boolean targetHoldsPermission = false;
if (targetUid >= 0) {
// First... does the target actually need this permission?
- if (checkHoldingPermissions(pi, grantUri, targetUid, modeFlags)) {
+ if (checkHoldingPermissionsUnlocked(pi, grantUri, targetUid, modeFlags)) {
// No need to grant the target this permission.
if (DEBUG) Slog.v(TAG,
"Target " + targetPkg + " already has full permission to " + grantUri);
@@ -1144,7 +1182,7 @@
*/
boolean specialCrossUserGrant = targetUid >= 0
&& UserHandle.getUserId(targetUid) != grantUri.sourceUserId
- && checkHoldingPermissionsInternal(pi, grantUri, callingUid,
+ && checkHoldingPermissionsInternalUnlocked(pi, grantUri, callingUid,
modeFlags, false /*without considering the uid permissions*/);
// Second... is the provider allowing granting of URI permissions?
@@ -1179,9 +1217,13 @@
}
// Third... does the caller itself have permission to access this uri?
- if (!checkHoldingPermissions(pi, grantUri, callingUid, modeFlags)) {
+ if (!checkHoldingPermissionsUnlocked(pi, grantUri, callingUid, modeFlags)) {
// Require they hold a strong enough Uri permission
- if (!checkUriPermission(grantUri, callingUid, modeFlags)) {
+ final boolean res;
+ synchronized (mLock) {
+ res = checkUriPermissionLocked(grantUri, callingUid, modeFlags);
+ }
+ if (!res) {
if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(pi.readPermission)) {
throw new SecurityException(
"UID " + callingUid + " does not have permission to " + grantUri
@@ -1200,13 +1242,14 @@
/**
* @param userId The userId in which the uri is to be resolved.
*/
- int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri, int modeFlags,
- int userId) {
- return checkGrantUriPermission(callingUid, targetPkg,
+ private int checkGrantUriPermissionUnlocked(int callingUid, String targetPkg, Uri uri,
+ int modeFlags, int userId) {
+ return checkGrantUriPermissionUnlocked(callingUid, targetPkg,
new GrantUri(userId, uri, modeFlags), modeFlags, -1);
}
- boolean checkUriPermission(GrantUri grantUri, int uid, final int modeFlags) {
+ @GuardedBy("mLock")
+ private boolean checkUriPermissionLocked(GrantUri grantUri, int uid, final int modeFlags) {
final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
: UriPermission.STRENGTH_OWNED;
@@ -1238,7 +1281,8 @@
return false;
}
- private void writeGrantedUriPermissions() {
+ @GuardedBy("mLock")
+ private void writeGrantedUriPermissionsLocked() {
if (DEBUG) Slog.v(TAG, "writeGrantedUriPermissions()");
final long startTime = SystemClock.uptimeMillis();
@@ -1299,34 +1343,35 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case PERSIST_URI_GRANTS_MSG: {
- writeGrantedUriPermissions();
+ synchronized (mLock) {
+ writeGrantedUriPermissionsLocked();
+ }
break;
}
}
}
}
- final class LocalService implements UriGrantsManagerInternal {
+ private final class LocalService implements UriGrantsManagerInternal {
@Override
public void removeUriPermissionIfNeeded(UriPermission perm) {
synchronized (mLock) {
- UriGrantsManagerService.this.removeUriPermissionIfNeeded(perm);
+ UriGrantsManagerService.this.removeUriPermissionIfNeededLocked(perm);
}
}
@Override
public void revokeUriPermission(String targetPackage, int callingUid, GrantUri grantUri,
int modeFlags) {
- synchronized (mLock) {
- UriGrantsManagerService.this.revokeUriPermission(
- targetPackage, callingUid, grantUri, modeFlags);
- }
+ UriGrantsManagerService.this.revokeUriPermission(
+ targetPackage, callingUid, grantUri, modeFlags);
}
@Override
public boolean checkUriPermission(GrantUri grantUri, int uid, int modeFlags) {
synchronized (mLock) {
- return UriGrantsManagerService.this.checkUriPermission(grantUri, uid, modeFlags);
+ return UriGrantsManagerService.this.checkUriPermissionLocked(grantUri, uid,
+ modeFlags);
}
}
@@ -1334,83 +1379,73 @@
public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri, int modeFlags,
int userId) {
enforceNotIsolatedCaller("checkGrantUriPermission");
- synchronized (mLock) {
- return UriGrantsManagerService.this.checkGrantUriPermission(
- callingUid, targetPkg, uri, modeFlags, userId);
- }
+ return UriGrantsManagerService.this.checkGrantUriPermissionUnlocked(
+ callingUid, targetPkg, uri, modeFlags, userId);
}
@Override
public NeededUriGrants checkGrantUriPermissionFromIntent(Intent intent, int callingUid,
String targetPkg, int targetUserId) {
- synchronized (mLock) {
- final int mode = (intent != null) ? intent.getFlags() : 0;
- return UriGrantsManagerService.this.checkGrantUriPermissionFromIntent(
- callingUid, targetPkg, intent, mode, null, targetUserId);
- }
+ final int mode = (intent != null) ? intent.getFlags() : 0;
+ return UriGrantsManagerService.this.checkGrantUriPermissionFromIntentUnlocked(
+ callingUid, targetPkg, intent, mode, null, targetUserId);
}
@Override
public void grantUriPermissionUncheckedFromIntent(NeededUriGrants needed,
UriPermissionOwner owner) {
- synchronized (mLock) {
- UriGrantsManagerService.this.grantUriPermissionUncheckedFromIntent(needed, owner);
- }
+ UriGrantsManagerService.this.grantUriPermissionUncheckedFromIntent(needed, owner);
}
@Override
public void onSystemReady() {
synchronized (mLock) {
- UriGrantsManagerService.this.readGrantedUriPermissions();
+ UriGrantsManagerService.this.readGrantedUriPermissionsLocked();
}
}
@Override
public IBinder newUriPermissionOwner(String name) {
enforceNotIsolatedCaller("newUriPermissionOwner");
- synchronized(mLock) {
- UriPermissionOwner owner = new UriPermissionOwner(this, name);
- return owner.getExternalToken();
- }
+ UriPermissionOwner owner = new UriPermissionOwner(this, name);
+ return owner.getExternalToken();
}
@Override
public void removeUriPermissionsForPackage(String packageName, int userHandle,
boolean persistable, boolean targetOnly) {
- synchronized(mLock) {
- UriGrantsManagerService.this.removeUriPermissionsForPackage(
+ synchronized (mLock) {
+ UriGrantsManagerService.this.removeUriPermissionsForPackageLocked(
packageName, userHandle, persistable, targetOnly);
}
}
@Override
public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
- synchronized(mLock) {
- final UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
- if (owner == null) {
- throw new IllegalArgumentException("Unknown owner: " + token);
- }
+ final UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
+ if (owner == null) {
+ throw new IllegalArgumentException("Unknown owner: " + token);
+ }
- if (uri == null) {
- owner.removeUriPermissions(mode);
- } else {
- owner.removeUriPermission(new GrantUri(userId, uri, mode), mode);
- }
+ if (uri == null) {
+ owner.removeUriPermissions(mode);
+ } else {
+ owner.removeUriPermission(new GrantUri(userId, uri, mode), mode);
}
}
@Override
public boolean checkAuthorityGrants(int callingUid, ProviderInfo cpi, int userId,
boolean checkUser) {
- synchronized(mLock) {
- return UriGrantsManagerService.this.checkAuthorityGrants(
+ synchronized (mLock) {
+ return UriGrantsManagerService.this.checkAuthorityGrantsLocked(
callingUid, cpi, userId, checkUser);
}
}
@Override
public void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
- synchronized(mLock) {
+ synchronized (mLock) {
boolean needSep = false;
boolean printedAnything = false;
if (mGrantedUriPermissions.size() > 0) {
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
index e86399e..62b6a65 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java
@@ -60,14 +60,12 @@
public class UriGrantsManagerServiceTest {
private UriGrantsMockContext mContext;
- private UriGrantsManagerService mService;
- private UriGrantsManagerInternal mLocalService;
+ private UriGrantsManagerInternal mService;
@Before
public void setUp() throws Exception {
mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext());
- mService = UriGrantsManagerService.createForTest(mContext.getFilesDir());
- mLocalService = mService.getLocalService();
+ mService = UriGrantsManagerService.createForTest(mContext.getFilesDir()).getLocalService();
}
/**
@@ -80,8 +78,7 @@
final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null,
- USER_PRIMARY);
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
assertEquals(PKG_SOCIAL, needed.targetPkg);
assertEquals(UID_PRIMARY_SOCIAL, needed.targetUid);
assertEquals(FLAG_READ, needed.flags);
@@ -98,8 +95,7 @@
final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null,
- USER_SECONDARY);
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
assertEquals(PKG_SOCIAL, needed.targetPkg);
assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid);
assertEquals(FLAG_READ, needed.flags);
@@ -113,8 +109,7 @@
public void testNeeded_public() {
final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PUBLIC).addFlags(FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_PUBLIC, PKG_SOCIAL, intent, intent.getFlags(), null,
- USER_PRIMARY);
+ intent, UID_PRIMARY_PUBLIC, PKG_SOCIAL, USER_PRIMARY);
assertNull(needed);
}
@@ -128,7 +123,7 @@
final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PUBLIC, FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_PUBLIC, PKG_SOCIAL, intent, intent.getFlags(), null, USER_SECONDARY);
+ intent, UID_PRIMARY_PUBLIC, PKG_SOCIAL, USER_SECONDARY);
assertEquals(PKG_SOCIAL, needed.targetPkg);
assertEquals(UID_SECONDARY_SOCIAL, needed.targetUid);
assertEquals(FLAG_READ, needed.flags);
@@ -143,7 +138,7 @@
final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PRIVATE).addFlags(FLAG_READ);
try {
mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_PRIVATE, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY);
+ intent, UID_PRIMARY_PRIVATE, PKG_SOCIAL, USER_PRIMARY);
fail();
} catch (SecurityException expected) {
}
@@ -158,7 +153,7 @@
final Intent intent = new Intent(Intent.ACTION_VIEW, URI_FORCE)
.addFlags(FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_FORCE, PKG_FORCE, intent, intent.getFlags(), null, USER_PRIMARY);
+ intent, UID_PRIMARY_FORCE, PKG_FORCE, USER_PRIMARY);
assertEquals(asSet(new GrantUri(USER_PRIMARY, URI_FORCE, 0)), needed.uris);
}
@@ -172,15 +167,15 @@
{
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- assertNull(mService.checkGrantUriPermissionFromIntent(UID_PRIMARY_COMPLEX, PKG_SOCIAL,
- intent, intent.getFlags(), null, USER_PRIMARY));
+ assertNull(mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY));
}
{
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ | FLAG_PREFIX);
try {
- mService.checkGrantUriPermissionFromIntent(UID_PRIMARY_COMPLEX, PKG_SOCIAL,
- intent, intent.getFlags(), null, USER_PRIMARY);
+ mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
fail();
} catch (SecurityException expected) {
}
@@ -189,8 +184,8 @@
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ | FLAG_PERSISTABLE);
try {
- mService.checkGrantUriPermissionFromIntent(UID_PRIMARY_COMPLEX, PKG_SOCIAL,
- intent, intent.getFlags(), null, USER_PRIMARY);
+ mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
fail();
} catch (SecurityException expected) {
}
@@ -209,8 +204,7 @@
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_COMPLEX, PKG_SOCIAL, intent, intent.getFlags(), null,
- USER_SECONDARY);
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY);
assertEquals(FLAG_READ, needed.flags);
}
{
@@ -218,8 +212,7 @@
.addFlags(FLAG_READ | FLAG_PREFIX);
try {
mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_COMPLEX, PKG_SOCIAL, intent, intent.getFlags(), null,
- USER_SECONDARY);
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY);
fail();
} catch (SecurityException expected) {
}
@@ -229,8 +222,7 @@
.addFlags(FLAG_READ | FLAG_PERSISTABLE);
try {
mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_COMPLEX, PKG_SOCIAL, intent, intent.getFlags(), null,
- USER_SECONDARY);
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_SECONDARY);
fail();
} catch (SecurityException expected) {
}
@@ -248,21 +240,21 @@
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_COMPLEX, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY);
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, 0)), needed.uris);
}
{
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ | FLAG_PREFIX);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_COMPLEX, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY);
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, FLAG_PREFIX)), needed.uris);
}
{
final Intent intent = new Intent(Intent.ACTION_VIEW, uri)
.addFlags(FLAG_READ | FLAG_PERSISTABLE);
final NeededUriGrants needed = mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_COMPLEX, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY);
+ intent, UID_PRIMARY_COMPLEX, PKG_SOCIAL, USER_PRIMARY);
assertEquals(asSet(new GrantUri(USER_PRIMARY, uri, 0)), needed.uris);
}
}
@@ -284,8 +276,8 @@
// When granting towards primary, persistable can't be honored so
// the entire grant fails
try {
- mService.checkGrantUriPermissionFromIntent(UID_PRIMARY_CAMERA, PKG_SOCIAL, intent,
- intent.getFlags(), null, USER_PRIMARY);
+ mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY);
fail();
} catch (SecurityException expected) {
}
@@ -294,8 +286,8 @@
// When granting towards secondary, persistable can't be honored so
// the entire grant fails
try {
- mService.checkGrantUriPermissionFromIntent(UID_PRIMARY_CAMERA, PKG_SOCIAL, intent,
- intent.getFlags(), null, USER_SECONDARY);
+ mService.checkGrantUriPermissionFromIntent(
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_SECONDARY);
fail();
} catch (SecurityException expected) {
}
@@ -310,18 +302,16 @@
public void testGrant_overlap() {
final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ);
- final UriPermissionOwner activity = new UriPermissionOwner(mLocalService, "activity");
- final UriPermissionOwner service = new UriPermissionOwner(mLocalService, "service");
+ final UriPermissionOwner activity = new UriPermissionOwner(mService, "activity");
+ final UriPermissionOwner service = new UriPermissionOwner(mService, "service");
final GrantUri expectedGrant = new GrantUri(USER_PRIMARY, URI_PHOTO_1, FLAG_READ);
// Grant read via activity and write via service
mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY),
- activity);
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), activity);
mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY),
- service);
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), service);
// Verify that everything is good with the world
assertTrue(mService.checkUriPermission(expectedGrant, UID_PRIMARY_SOCIAL, FLAG_READ));
@@ -338,7 +328,7 @@
@Test
public void testCheckAuthorityGrants() {
final Intent intent = new Intent(Intent.ACTION_VIEW, URI_PHOTO_1).addFlags(FLAG_READ);
- final UriPermissionOwner owner = new UriPermissionOwner(mLocalService, "primary");
+ final UriPermissionOwner owner = new UriPermissionOwner(mService, "primary");
final ProviderInfo cameraInfo = mContext.mPmInternal.resolveContentProvider(
PKG_CAMERA, 0, USER_PRIMARY);
@@ -355,8 +345,7 @@
// Granting primary camera to primary social
mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
- UID_PRIMARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY),
- owner);
+ intent, UID_PRIMARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), owner);
assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
cameraInfo, USER_PRIMARY, true));
assertFalse(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
@@ -368,8 +357,7 @@
// Granting secondary camera to primary social
mService.grantUriPermissionUncheckedFromIntent(mService.checkGrantUriPermissionFromIntent(
- UID_SECONDARY_CAMERA, PKG_SOCIAL, intent, intent.getFlags(), null, USER_PRIMARY),
- owner);
+ intent, UID_SECONDARY_CAMERA, PKG_SOCIAL, USER_PRIMARY), owner);
assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,
cameraInfo, USER_PRIMARY, true));
assertTrue(mService.checkAuthorityGrants(UID_PRIMARY_SOCIAL,