diff options
16 files changed, 376 insertions, 1553 deletions
diff --git a/core/tests/coretests/src/android/view/inputmethod/DeleteRangeGestureTest.java b/core/tests/coretests/src/android/view/inputmethod/DeleteRangeGestureTest.java new file mode 100644 index 000000000000..d7b911dda672 --- /dev/null +++ b/core/tests/coretests/src/android/view/inputmethod/DeleteRangeGestureTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.graphics.RectF; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.compatibility.common.util.ApiTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +@ApiTest(apis = {"android.view.inputmethod.DeleteRangeGesture.Builder#setGranularity", + "android.view.inputmethod.DeleteRangeGesture.Builder#setDeletionStartArea", + "android.view.inputmethod.DeleteRangeGesture.Builder#setDeletionEndArea", + "android.view.inputmethod.DeleteRangeGesture.Builder#setFallbackText", + "android.view.inputmethod.DeleteRangeGesture.Builder#build"}) +public class DeleteRangeGestureTest { + private static final RectF DELETION_START_RECTANGLE = new RectF(1, 2, 3, 4); + private static final RectF DELETION_END_RECTANGLE = new RectF(0, 2, 3, 4); + private static final String FALLBACK_TEXT = "fallback_test"; + + @Test + public void testBuilder() { + DeleteRangeGesture.Builder builder = new DeleteRangeGesture.Builder(); + DeleteRangeGesture gesture = builder.setGranularity(HandwritingGesture.GRANULARITY_WORD) + .setDeletionStartArea(DELETION_START_RECTANGLE) + .setDeletionEndArea(DELETION_END_RECTANGLE) + .setFallbackText(FALLBACK_TEXT).build(); + assertNotNull(gesture); + assertEquals(HandwritingGesture.GRANULARITY_WORD, gesture.getGranularity()); + assertEquals(DELETION_START_RECTANGLE, gesture.getDeletionStartArea()); + assertEquals(DELETION_END_RECTANGLE, gesture.getDeletionEndArea()); + assertEquals(FALLBACK_TEXT, gesture.getFallbackText()); + } +} diff --git a/core/tests/coretests/src/android/view/inputmethod/InsertGestureTest.java b/core/tests/coretests/src/android/view/inputmethod/InsertGestureTest.java new file mode 100644 index 000000000000..47a724d36038 --- /dev/null +++ b/core/tests/coretests/src/android/view/inputmethod/InsertGestureTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.graphics.PointF; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.compatibility.common.util.ApiTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +@ApiTest(apis = {"android.view.inputmethod.InsertGesture.Builder#setInsertionPoint", + "android.view.inputmethod.InsertGesture.Builder#setTextToInsert", + "android.view.inputmethod.InsertGesture.Builder#setFallbackText", + "android.view.inputmethod.InsertGesture.Builder#build"}) +public class InsertGestureTest { + private static final PointF INSERTION_POINT = new PointF(1, 2); + private static final String FALLBACK_TEXT = "fallback_text"; + private static final String TEXT_TO_INSERT = "text"; + + @Test + public void testBuilder() { + InsertGesture.Builder builder = new InsertGesture.Builder(); + InsertGesture gesture = builder.setInsertionPoint(INSERTION_POINT) + .setTextToInsert(TEXT_TO_INSERT) + .setFallbackText(FALLBACK_TEXT).build(); + assertNotNull(gesture); + assertEquals(INSERTION_POINT, gesture.getInsertionPoint()); + assertEquals(FALLBACK_TEXT, gesture.getFallbackText()); + assertEquals(TEXT_TO_INSERT, gesture.getTextToInsert()); + } +} diff --git a/core/tests/coretests/src/android/view/inputmethod/InsertModeGestureTest.java b/core/tests/coretests/src/android/view/inputmethod/InsertModeGestureTest.java new file mode 100644 index 000000000000..11ddba110f7a --- /dev/null +++ b/core/tests/coretests/src/android/view/inputmethod/InsertModeGestureTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.graphics.PointF; +import android.os.CancellationSignal; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.compatibility.common.util.ApiTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +@ApiTest(apis = {"android.view.inputmethod.InsertModeGesture.Builder#setInsertionPoint", + "android.view.inputmethod.InsertModeGesture.Builder#setCancellationSignal", + "android.view.inputmethod.InsertModeGesture.Builder#setFallbackText", + "android.view.inputmethod.InsertModeGesture.Builder#build"}) +public class InsertModeGestureTest { + private static final PointF INSERTION_POINT = new PointF(1, 2); + private static final String FALLBACK_TEXT = "fallback_text"; + private static final CancellationSignal CANCELLATION_SIGNAL = new CancellationSignal(); + + @Test + public void testBuilder() { + InsertModeGesture.Builder builder = new InsertModeGesture.Builder(); + InsertModeGesture gesture = builder.setInsertionPoint(INSERTION_POINT) + .setCancellationSignal(CANCELLATION_SIGNAL) + .setFallbackText(FALLBACK_TEXT).build(); + assertNotNull(gesture); + assertEquals(INSERTION_POINT, gesture.getInsertionPoint()); + assertEquals(FALLBACK_TEXT, gesture.getFallbackText()); + assertEquals(CANCELLATION_SIGNAL, gesture.getCancellationSignal()); + } +} diff --git a/core/tests/coretests/src/android/view/inputmethod/SelectGestureTest.java b/core/tests/coretests/src/android/view/inputmethod/SelectGestureTest.java new file mode 100644 index 000000000000..b2eb07c0a9e7 --- /dev/null +++ b/core/tests/coretests/src/android/view/inputmethod/SelectGestureTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.graphics.RectF; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.compatibility.common.util.ApiTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +@ApiTest(apis = {"android.view.inputmethod.SelectGesture.Builder#setGranularity", + "android.view.inputmethod.SelectGesture.Builder#setSelectionArea", + "android.view.inputmethod.SelectGesture.Builder#setFallbackText", + "android.view.inputmethod.SelectGesture.Builder#build"}) +public class SelectGestureTest { + private static final RectF SELECTION_RECTANGLE = new RectF(1, 2, 3, 4); + private static final String FALLBACK_TEXT = "fallback_text"; + + @Test + public void testBuilder() { + SelectGesture.Builder builder = new SelectGesture.Builder(); + SelectGesture gesture = builder.setGranularity(HandwritingGesture.GRANULARITY_WORD) + .setSelectionArea(SELECTION_RECTANGLE) + .setFallbackText(FALLBACK_TEXT).build(); + assertNotNull(gesture); + assertEquals(HandwritingGesture.GRANULARITY_WORD, gesture.getGranularity()); + assertEquals(SELECTION_RECTANGLE, gesture.getSelectionArea()); + assertEquals(FALLBACK_TEXT, gesture.getFallbackText()); + } +} diff --git a/core/tests/coretests/src/android/view/inputmethod/SelectRangeGestureTest.java b/core/tests/coretests/src/android/view/inputmethod/SelectRangeGestureTest.java new file mode 100644 index 000000000000..df63a4aaaefe --- /dev/null +++ b/core/tests/coretests/src/android/view/inputmethod/SelectRangeGestureTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.graphics.RectF; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.compatibility.common.util.ApiTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +@ApiTest(apis = {"android.view.inputmethod.SelectRangeGesture.Builder#setGranularity", + "android.view.inputmethod.SelectRangeGesture.Builder#setSelectionStartArea", + "android.view.inputmethod.SelectRangeGesture.Builder#setSelectionEndArea", + "android.view.inputmethod.SelectRangeGesture.Builder#setFallbackText", + "android.view.inputmethod.SelectRangeGesture.Builder#build"}) +public class SelectRangeGestureTest { + private static final RectF SELECTION_START_RECTANGLE = new RectF(1, 2, 3, 4); + private static final RectF SELECTION_END_RECTANGLE = new RectF(0, 2, 3, 4); + private static final String FALLBACK_TEXT = "fallback_text"; + + @Test + public void testBuilder() { + SelectRangeGesture.Builder builder = new SelectRangeGesture.Builder(); + SelectRangeGesture gesture = builder.setGranularity(HandwritingGesture.GRANULARITY_WORD) + .setSelectionStartArea(SELECTION_START_RECTANGLE) + .setSelectionEndArea(SELECTION_END_RECTANGLE) + .setFallbackText(FALLBACK_TEXT).build(); + assertNotNull(gesture); + assertEquals(HandwritingGesture.GRANULARITY_WORD, gesture.getGranularity()); + assertEquals(SELECTION_START_RECTANGLE, gesture.getSelectionStartArea()); + assertEquals(SELECTION_END_RECTANGLE, gesture.getSelectionEndArea()); + assertEquals(FALLBACK_TEXT, gesture.getFallbackText()); + } +} diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml index 6354752e1b22..763930db1d55 100644 --- a/packages/SystemUI/res/values/flags.xml +++ b/packages/SystemUI/res/values/flags.xml @@ -30,9 +30,6 @@ <bool name="flag_charging_ripple">false</bool> - <!-- Whether to show chipbar UI whenever the device is unlocked by ActiveUnlock. --> - <bool name="flag_active_unlock_chipbar">true</bool> - <!-- Whether the user switcher chip shows in the status bar. When true, the multi user avatar will no longer show on the lockscreen --> <bool name="flag_user_switcher_chip">false</bool> diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 2666d94841a7..c0e11336b46f 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -162,12 +162,6 @@ object Flags { val CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES = releasedFlag(216, "customizable_lock_screen_quick_affordances") - /** Shows chipbar UI whenever the device is unlocked by ActiveUnlock (watch). */ - // TODO(b/256513609): Tracking Bug - @JvmField - val ACTIVE_UNLOCK_CHIPBAR = - resourceBooleanFlag(217, R.bool.flag_active_unlock_chipbar, "active_unlock_chipbar") - /** * Migrates control of the LightRevealScrim's reveal effect and amount from legacy code to the * new KeyguardTransitionRepository. @@ -284,8 +278,7 @@ object Flags { /** Enables new QS Edit Mode visual refresh */ // TODO(b/269787742): Tracking Bug @JvmField - val ENABLE_NEW_QS_EDIT_MODE = - unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false) + val ENABLE_NEW_QS_EDIT_MODE = unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false) // 600- status bar diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index baa812c63aa7..584d27f84ceb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -635,7 +635,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca && mLastKeyguardAndExpanded == onKeyguardAndExpanded && mLastViewHeight == currentHeight && mLastHeaderTranslation == headerTranslation - && mSquishinessFraction == squishinessFraction) { + && mSquishinessFraction == squishinessFraction + && mLastPanelFraction == panelExpansionFraction) { return; } mLastHeaderTranslation = headerTranslation; diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 587c65d44091..30865aa0c45d 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -3779,10 +3779,10 @@ public final class NotificationPanelViewController implements Dumpable { mHeightAnimator.end(); } } - mQsController.setShadeExpandedHeight(mExpandedHeight); - mExpansionDragDownAmountPx = h; mExpandedFraction = Math.min(1f, maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); + mQsController.setShadeExpansion(mExpandedHeight, mExpandedFraction); + mExpansionDragDownAmountPx = h; mAmbientState.setExpansionFraction(mExpandedFraction); onHeightUpdated(mExpandedHeight); updatePanelExpansionAndVisibility(); diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java index df8ae50682fc..9f467074d473 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java @@ -351,7 +351,6 @@ public class QuickSettingsController { mFeatureFlags = featureFlags; mInteractionJankMonitor = interactionJankMonitor; - mShadeExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged); mLockscreenShadeTransitionController.addCallback(new LockscreenShadeTransitionCallback()); } @@ -878,8 +877,9 @@ public class QuickSettingsController { mCollapsedOnDown = collapsedOnDown; } - void setShadeExpandedHeight(float shadeExpandedHeight) { - mShadeExpandedHeight = shadeExpandedHeight; + void setShadeExpansion(float expandedHeight, float expandedFraction) { + mShadeExpandedHeight = expandedHeight; + mShadeExpandedFraction = expandedFraction; } @VisibleForTesting @@ -1749,11 +1749,6 @@ public class QuickSettingsController { return false; } - @VisibleForTesting - void onPanelExpansionChanged(ShadeExpansionChangeEvent event) { - mShadeExpandedFraction = event.getFraction(); - } - /** * Animate QS closing by flinging it. * If QS is expanded, it will collapse into QQS and stop. diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java index 15b84238dd19..d8ffe39e427d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java @@ -275,9 +275,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase { @Test public void testPanelStaysOpenWhenClosingQs() { - mShadeExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 1, - /* expanded= */ true, /* tracking= */ false, /* dragDownPxAmount= */ 0); - mQsController.setShadeExpandedHeight(1); + mQsController.setShadeExpansion(/* shadeExpandedHeight= */ 1, /* expandedFraction=*/ 1); float shadeExpandedHeight = mQsController.getShadeExpandedHeight(); mQsController.animateCloseQs(false); @@ -289,7 +287,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase { public void interceptTouchEvent_withinQs_shadeExpanded_startsQsTracking() { mQsController.setQs(mQs); - mQsController.setShadeExpandedHeight(1f); + mQsController.setShadeExpansion(/* shadeExpandedHeight= */ 1, /* expandedFraction=*/ 1); mQsController.onIntercept( createMotionEvent(0, 0, ACTION_DOWN)); mQsController.onIntercept( @@ -303,7 +301,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase { enableSplitShade(true); mQsController.setQs(mQs); - mQsController.setShadeExpandedHeight(1f); + mQsController.setShadeExpansion(/* shadeExpandedHeight= */ 1, /* expandedFraction=*/ 1); mQsController.onIntercept( createMotionEvent(0, 0, ACTION_DOWN)); mQsController.onIntercept( @@ -342,13 +340,8 @@ public class QuickSettingsControllerTest extends SysuiTestCase { public void handleTouch_downActionInQsArea() { mQsController.setQs(mQs); mQsController.setBarState(SHADE); - mQsController.onPanelExpansionChanged( - new ShadeExpansionChangeEvent( - 0.5f, - true, - true, - 0 - )); + mQsController.setShadeExpansion(/* shadeExpandedHeight= */ 1, /* expandedFraction=*/ 0.5f); + MotionEvent event = createMotionEvent(QS_FRAME_WIDTH / 2, QS_FRAME_BOTTOM / 2, ACTION_DOWN); mQsController.handleTouch(event, false, false); @@ -385,7 +378,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase { @Test public void handleTouch_isConflictingExpansionGestureSet() { assertThat(mQsController.isConflictingExpansionGesture()).isFalse(); - mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f); + mQsController.setShadeExpansion(/* shadeExpandedHeight= */ 1, /* expandedFraction=*/ 1); mQsController.handleTouch(MotionEvent.obtain(0L /* downTime */, 0L /* eventTime */, ACTION_DOWN, 0f /* x */, 0f /* y */, 0 /* metaState */), false, false); @@ -394,7 +387,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase { @Test public void handleTouch_isConflictingExpansionGestureSet_cancel() { - mShadeExpansionStateManager.onPanelExpansionChanged(1f, true, false, 0f); + mQsController.setShadeExpansion(/* shadeExpandedHeight= */ 1, /* expandedFraction=*/ 1); mQsController.handleTouch(createMotionEvent(0, 0, ACTION_DOWN), false, false); assertThat(mQsController.isConflictingExpansionGesture()).isTrue(); mQsController.handleTouch(createMotionEvent(0, 0, ACTION_UP), true, true); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java index 06fc41626e50..dbc824c384a2 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java @@ -68,6 +68,7 @@ import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.SharedMemory; +import android.service.voice.DetectorFailure; import android.service.voice.HotwordDetectedResult; import android.service.voice.HotwordDetectionService; import android.service.voice.HotwordDetectionServiceFailure; @@ -623,11 +624,9 @@ abstract class DetectorSession { mRemoteDetectionService = remoteDetectionService; } - void reportErrorLocked(int errorCode, @NonNull String errorMessage) { + void reportErrorLocked(@NonNull DetectorFailure detectorFailure) { try { - // TODO: Use instanceof(this) to get different detector to set the right error source. - mCallback.onDetectionFailure( - new HotwordDetectionServiceFailure(errorCode, errorMessage)); + mCallback.onDetectionFailure(detectorFailure); } catch (RemoteException e) { Slog.w(TAG, "Failed to report onError status: " + e); if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 025e1dc78c86..4fd5979b3d9f 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -51,11 +51,14 @@ import android.os.ServiceManager; import android.os.SharedMemory; import android.provider.DeviceConfig; import android.service.voice.HotwordDetectionService; +import android.service.voice.HotwordDetectionServiceFailure; import android.service.voice.HotwordDetector; import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback; import android.service.voice.ISandboxedDetectionService; import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback; +import android.service.voice.UnknownFailure; import android.service.voice.VisualQueryDetectionService; +import android.service.voice.VisualQueryDetectionServiceFailure; import android.service.voice.VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity; import android.speech.IRecognitionServiceManager; import android.util.Slog; @@ -109,6 +112,16 @@ final class HotwordDetectionConnection { private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour private static final int MAX_ISOLATED_PROCESS_NUMBER = 10; + /** + * Indicates the {@link HotwordDetectionService} is created. + */ + private static final int DETECTION_SERVICE_TYPE_HOTWORD = 1; + + /** + * Indicates the {@link VisualQueryDetectionService} is created. + */ + private static final int DETECTION_SERVICE_TYPE_VISUAL_QUERY = 2; + // TODO: This may need to be a Handler(looper) private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); @@ -186,11 +199,11 @@ final class HotwordDetectionConnection { mHotwordDetectionServiceConnectionFactory = new ServiceConnectionFactory(hotwordDetectionServiceIntent, - bindInstantServiceAllowed); + bindInstantServiceAllowed, DETECTION_SERVICE_TYPE_HOTWORD); mVisualQueryDetectionServiceConnectionFactory = new ServiceConnectionFactory(visualQueryDetectionServiceIntent, - bindInstantServiceAllowed); + bindInstantServiceAllowed, DETECTION_SERVICE_TYPE_VISUAL_QUERY); mLastRestartInstant = Instant.now(); @@ -604,17 +617,20 @@ final class HotwordDetectionConnection { private class ServiceConnectionFactory { private final Intent mIntent; private final int mBindingFlags; + private final int mDetectionServiceType; - ServiceConnectionFactory(@NonNull Intent intent, boolean bindInstantServiceAllowed) { + ServiceConnectionFactory(@NonNull Intent intent, boolean bindInstantServiceAllowed, + int detectionServiceType) { mIntent = intent; mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0; + mDetectionServiceType = detectionServiceType; } ServiceConnection createLocked() { ServiceConnection connection = new ServiceConnection(mContext, mIntent, mBindingFlags, mUser, ISandboxedDetectionService.Stub::asInterface, - mRestartCount % MAX_ISOLATED_PROCESS_NUMBER); + mRestartCount % MAX_ISOLATED_PROCESS_NUMBER, mDetectionServiceType); connection.connect(); updateAudioFlinger(connection, mAudioFlinger); @@ -635,15 +651,17 @@ final class HotwordDetectionConnection { private boolean mRespectServiceConnectionStatusChanged = true; private boolean mIsBound = false; private boolean mIsLoggedFirstConnect = false; + private final int mDetectionServiceType; ServiceConnection(@NonNull Context context, @NonNull Intent serviceIntent, int bindingFlags, int userId, @Nullable Function<IBinder, ISandboxedDetectionService> binderAsInterface, - int instanceNumber) { + int instanceNumber, int detectionServiceType) { super(context, serviceIntent, bindingFlags, userId, binderAsInterface); this.mIntent = serviceIntent; this.mBindingFlags = bindingFlags; this.mInstanceNumber = instanceNumber; + this.mDetectionServiceType = detectionServiceType; } @Override // from ServiceConnector.Impl @@ -660,14 +678,14 @@ final class HotwordDetectionConnection { mIsBound = connected; if (!connected) { - if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { + if (mDetectionServiceType != DETECTION_SERVICE_TYPE_VISUAL_QUERY) { HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HOTWORD_DETECTOR_EVENTS__EVENT__ON_DISCONNECTED, mVoiceInteractionServiceUid); } } else if (!mIsLoggedFirstConnect) { mIsLoggedFirstConnect = true; - if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { + if (mDetectionServiceType != DETECTION_SERVICE_TYPE_VISUAL_QUERY) { HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED, mVoiceInteractionServiceUid); @@ -684,7 +702,7 @@ final class HotwordDetectionConnection { @Override public void binderDied() { super.binderDied(); - Slog.w(TAG, "binderDied"); + Slog.w(TAG, "binderDied mDetectionServiceType = " + mDetectionServiceType); synchronized (mLock) { if (!mRespectServiceConnectionStatusChanged) { Slog.v(TAG, "Ignored #binderDied event"); @@ -693,13 +711,10 @@ final class HotwordDetectionConnection { } //TODO(b265535257): report error to either service only. synchronized (HotwordDetectionConnection.this.mLock) { - runForEachDetectorSessionLocked((session) -> { - session.reportErrorLocked(DetectorSession.HOTWORD_DETECTION_SERVICE_DIED, - "Detection service is dead."); - }); + runForEachDetectorSessionLocked(this::reportBinderDiedLocked); } // Can improve to log exit reason if needed - if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { + if (mDetectionServiceType != DETECTION_SERVICE_TYPE_VISUAL_QUERY) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__SERVICE_CRASH, @@ -711,7 +726,7 @@ final class HotwordDetectionConnection { protected boolean bindService( @NonNull android.content.ServiceConnection serviceConnection) { try { - if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { + if (mDetectionServiceType != DETECTION_SERVICE_TYPE_VISUAL_QUERY) { HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE, mVoiceInteractionServiceUid); @@ -723,7 +738,12 @@ final class HotwordDetectionConnection { mExecutor, serviceConnection); if (!bindResult) { - if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { + Slog.w(TAG, + "bindService failure mDetectionServiceType = " + mDetectionServiceType); + synchronized (HotwordDetectionConnection.this.mLock) { + runForEachDetectorSessionLocked(this::reportBindServiceFailureLocked); + } + if (mDetectionServiceType != DETECTION_SERVICE_TYPE_VISUAL_QUERY) { HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL, mVoiceInteractionServiceUid); @@ -731,7 +751,7 @@ final class HotwordDetectionConnection { } return bindResult; } catch (IllegalArgumentException e) { - if (mDetectorType != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) { + if (mDetectionServiceType != DETECTION_SERVICE_TYPE_VISUAL_QUERY) { HotwordMetricsLogger.writeDetectorEvent(mDetectorType, HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL, mVoiceInteractionServiceUid); @@ -752,6 +772,42 @@ final class HotwordDetectionConnection { mRespectServiceConnectionStatusChanged = false; } } + + private void reportBinderDiedLocked(DetectorSession detectorSession) { + if (mDetectionServiceType == DETECTION_SERVICE_TYPE_HOTWORD && ( + detectorSession instanceof DspTrustedHotwordDetectorSession + || detectorSession instanceof SoftwareTrustedHotwordDetectorSession)) { + detectorSession.reportErrorLocked(new HotwordDetectionServiceFailure( + HotwordDetectionServiceFailure.ERROR_CODE_BINDING_DIED, + "Detection service is dead.")); + } else if (mDetectionServiceType == DETECTION_SERVICE_TYPE_VISUAL_QUERY + && detectorSession instanceof VisualQueryDetectorSession) { + detectorSession.reportErrorLocked(new VisualQueryDetectionServiceFailure( + VisualQueryDetectionServiceFailure.ERROR_CODE_BINDING_DIED, + "Detection service is dead.")); + } else { + detectorSession.reportErrorLocked(new UnknownFailure( + "Detection service is dead with unknown detection service type.")); + } + } + + private void reportBindServiceFailureLocked(DetectorSession detectorSession) { + if (mDetectionServiceType == DETECTION_SERVICE_TYPE_HOTWORD && ( + detectorSession instanceof DspTrustedHotwordDetectorSession + || detectorSession instanceof SoftwareTrustedHotwordDetectorSession)) { + detectorSession.reportErrorLocked(new HotwordDetectionServiceFailure( + HotwordDetectionServiceFailure.ERROR_CODE_BIND_FAILURE, + "Bind detection service failure.")); + } else if (mDetectionServiceType == DETECTION_SERVICE_TYPE_VISUAL_QUERY + && detectorSession instanceof VisualQueryDetectorSession) { + detectorSession.reportErrorLocked(new VisualQueryDetectionServiceFailure( + VisualQueryDetectionServiceFailure.ERROR_CODE_BIND_FAILURE, + "Bind detection service failure.")); + } else { + detectorSession.reportErrorLocked(new UnknownFailure( + "Bind detection service failure with unknown detection service type.")); + } + } } @SuppressWarnings("GuardedBy") diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt index 423a6843891e..b4f6a1c12d8f 100644 --- a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt +++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt @@ -36,7 +36,6 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() { CallingSettingsNonUserGetterMethodsDetector.ISSUE_NON_USER_GETTER_CALLED, SaferParcelChecker.ISSUE_UNSAFE_API_USAGE, PackageVisibilityDetector.ISSUE_PACKAGE_NAME_NO_PACKAGE_VISIBILITY_FILTERS, - RegisterReceiverFlagDetector.ISSUE_RECEIVER_EXPORTED_FLAG, PermissionMethodDetector.ISSUE_PERMISSION_METHOD_USAGE, PermissionMethodDetector.ISSUE_CAN_BE_PERMISSION_METHOD, ) diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt deleted file mode 100644 index c3e0428316c3..000000000000 --- a/tools/lint/framework/checks/src/main/java/com/google/android/lint/RegisterReceiverFlagDetector.kt +++ /dev/null @@ -1,927 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.lint - -import com.android.tools.lint.checks.DataFlowAnalyzer -import com.android.tools.lint.detector.api.Category -import com.android.tools.lint.detector.api.ConstantEvaluator -import com.android.tools.lint.detector.api.Detector -import com.android.tools.lint.detector.api.Implementation -import com.android.tools.lint.detector.api.Issue -import com.android.tools.lint.detector.api.JavaContext -import com.android.tools.lint.detector.api.Scope -import com.android.tools.lint.detector.api.Severity -import com.android.tools.lint.detector.api.SourceCodeScanner -import com.android.tools.lint.detector.api.UastLintUtils.Companion.findLastAssignment -import com.android.tools.lint.detector.api.getMethodName -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiVariable -import org.jetbrains.kotlin.psi.psiUtil.parameterIndex -import org.jetbrains.uast.UCallExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UExpression -import org.jetbrains.uast.UParenthesizedExpression -import org.jetbrains.uast.UQualifiedReferenceExpression -import org.jetbrains.uast.getContainingUMethod -import org.jetbrains.uast.isNullLiteral -import org.jetbrains.uast.skipParenthesizedExprDown -import org.jetbrains.uast.tryResolve - -/** - * Detector that identifies `registerReceiver()` calls which are missing the `RECEIVER_EXPORTED` or - * `RECEIVER_NOT_EXPORTED` flags on T+. - * - * TODO: Add API level conditions to better support non-platform code. - * 1. Check if registerReceiver() call is reachable on T+. - * 2. Check if targetSdkVersion is T+. - * - * eg: isWithinVersionCheckConditional(context, node, 31, false) - * eg: isPrecededByVersionCheckExit(context, node, 31) ? - */ -@Suppress("UnstableApiUsage") -class RegisterReceiverFlagDetector : Detector(), SourceCodeScanner { - - override fun getApplicableMethodNames(): List<String> = listOf( - "registerReceiver", - "registerReceiverAsUser", - "registerReceiverForAllUsers" - ) - - private fun checkIsProtectedReceiverAndReturnUnprotectedActions( - filterArg: UExpression, - node: UCallExpression, - evaluator: ConstantEvaluator - ): Pair<Boolean, List<String>> { // isProtected, unprotectedActions - val actions = mutableSetOf<String>() - val construction = findIntentFilterConstruction(filterArg, node) - - if (construction == null) return Pair(false, listOf<String>()) - val constructorActionArg = construction.getArgumentForParameter(0) - (constructorActionArg?.let(evaluator::evaluate) as? String)?.let(actions::add) - - val actionCollectorVisitor = - ActionCollectorVisitor(setOf(construction), node, evaluator) - - val parent = node.getContainingUMethod() - parent?.accept(actionCollectorVisitor) - actions.addAll(actionCollectorVisitor.actions) - - // If we failed to evaluate any actions, there will be a null action in the set. - val isProtected = - actions.all(PROTECTED_BROADCASTS::contains) && - !actionCollectorVisitor.intentFilterEscapesScope - val unprotectedActionsList = actions.filterNot(PROTECTED_BROADCASTS::contains) - return Pair(isProtected, unprotectedActionsList) - } - - override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { - if (!context.evaluator.isMemberInSubClassOf(method, "android.content.Context")) return - - // The parameter positions vary across the various registerReceiver*() methods, so rather - // than hardcode them we simply look them up based on the parameter name and type. - val receiverArg = - findArgument(node, method, "android.content.BroadcastReceiver", "receiver") - val filterArg = findArgument(node, method, "android.content.IntentFilter", "filter") - val flagsArg = findArgument(node, method, "int", "flags") - - if (receiverArg == null || receiverArg.isNullLiteral() || filterArg == null) { - return - } - - val evaluator = ConstantEvaluator().allowFieldInitializers() - - val (isProtected, unprotectedActionsList) = - checkIsProtectedReceiverAndReturnUnprotectedActions(filterArg, node, evaluator) - - val flags = evaluator.evaluate(flagsArg) as? Int - - if (!isProtected) { - val actionsList = unprotectedActionsList.joinToString(", ", "", "", -1, "") - val message = "$receiverArg is missing 'RECEIVED_EXPORTED` or 'RECEIVE_NOT_EXPORTED' " + - "flag for unprotected broadcast(s) registered for $actionsList." - if (flagsArg == null) { - context.report( - ISSUE_RECEIVER_EXPORTED_FLAG, node, context.getLocation(node), message) - } else if (flags != null && (flags and RECEIVER_EXPORTED_FLAG_PRESENT_MASK) == 0) { - context.report( - ISSUE_RECEIVER_EXPORTED_FLAG, node, context.getLocation(flagsArg), message) - } - } - - if (DEBUG) { - println(node.asRenderString()) - println("Unprotected Actions: $unprotectedActionsList") - println("Protected: $isProtected") - println("Flags: $flags") - } - } - - /** Finds the first argument of a method that matches the given parameter type and name. */ - private fun findArgument( - node: UCallExpression, - method: PsiMethod, - type: String, - name: String - ): UExpression? { - val psiParameter = method.parameterList.parameters.firstOrNull { - it.type.canonicalText == type && it.name == name - } ?: return null - val argument = node.getArgumentForParameter(psiParameter.parameterIndex()) - return argument?.skipParenthesizedExprDown() - } - - /** - * For the supplied expression (eg. intent filter argument), attempts to find its construction. - * This will be an `IntentFilter()` constructor, an `IntentFilter.create()` call, or `null`. - */ - private fun findIntentFilterConstruction( - expression: UExpression, - node: UCallExpression - ): UCallExpression? { - val resolved = expression.tryResolve() - - if (resolved is PsiVariable) { - val assignment = findLastAssignment(resolved, node) ?: return null - return findIntentFilterConstruction(assignment, node) - } - - if (expression is UParenthesizedExpression) { - return findIntentFilterConstruction(expression.expression, node) - } - - if (expression is UQualifiedReferenceExpression) { - val call = expression.selector as? UCallExpression ?: return null - return if (isReturningContext(call)) { - // eg. filter.apply { addAction("abc") } --> use filter variable. - findIntentFilterConstruction(expression.receiver, node) - } else { - // eg. IntentFilter.create("abc") --> use create("abc") UCallExpression. - findIntentFilterConstruction(call, node) - } - } - - val method = resolved as? PsiMethod ?: return null - return if (isIntentFilterFactoryMethod(method)) { - expression as? UCallExpression - } else { - null - } - } - - private fun isIntentFilterFactoryMethod(method: PsiMethod) = - (method.containingClass?.qualifiedName == "android.content.IntentFilter" && - (method.returnType?.canonicalText == "android.content.IntentFilter" || - method.isConstructor)) - - /** - * Returns true if the given call represents a Kotlin scope function where the return value is - * the context object; see https://kotlinlang.org/docs/scope-functions.html#function-selection. - */ - private fun isReturningContext(node: UCallExpression): Boolean { - val name = getMethodName(node) - if (name == "apply" || name == "also") { - return isScopingFunction(node) - } - return false - } - - /** - * Returns true if the given node appears to be one of the scope functions. Only checks parent - * class; caller should intend that it's actually one of let, with, apply, etc. - */ - private fun isScopingFunction(node: UCallExpression): Boolean { - val called = node.resolve() ?: return true - // See libraries/stdlib/jvm/build/stdlib-declarations.json - return called.containingClass?.qualifiedName == "kotlin.StandardKt__StandardKt" - } - - inner class ActionCollectorVisitor( - start: Collection<UElement>, - val functionCall: UCallExpression, - val evaluator: ConstantEvaluator, - ) : DataFlowAnalyzer(start) { - private var finished = false - var intentFilterEscapesScope = false; private set - val actions = mutableSetOf<String>() - - override fun argument(call: UCallExpression, reference: UElement) { - // TODO: Remove this temporary fix for DataFlowAnalyzer bug (ag/15787550): - if (reference !in call.valueArguments) return - val methodNames = super@RegisterReceiverFlagDetector.getApplicableMethodNames() - when { - finished -> return - // We've reached the registerReceiver*() call in question. - call == functionCall -> finished = true - // The filter 'intentFilterEscapesScope' to a method which could modify it. - methodNames != null && getMethodName(call)!! !in methodNames -> - intentFilterEscapesScope = true - } - } - - // Fixed in b/199163915: DataFlowAnalyzer doesn't call this for Kotlin properties. - override fun field(field: UElement) { - if (!finished) intentFilterEscapesScope = true - } - - override fun receiver(call: UCallExpression) { - if (!finished && getMethodName(call) == "addAction") { - val actionArg = call.getArgumentForParameter(0) - if (actionArg != null) { - val action = evaluator.evaluate(actionArg) as? String - if (action != null) actions.add(action) - } - } - } - } - - companion object { - const val DEBUG = false - - private const val RECEIVER_EXPORTED = 0x2 - private const val RECEIVER_NOT_EXPORTED = 0x4 - private const val RECEIVER_EXPORTED_FLAG_PRESENT_MASK = - RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED - - @JvmField - val ISSUE_RECEIVER_EXPORTED_FLAG: Issue = Issue.create( - id = "UnspecifiedRegisterReceiverFlag", - briefDescription = "Missing `registerReceiver()` exported flag", - explanation = """ - Apps targeting Android T (SDK 33) and higher must specify either `RECEIVER_EXPORTED` \ - or `RECEIVER_NOT_EXPORTED` when registering a broadcast receiver, unless the \ - receiver is only registered for protected system broadcast actions. - """, - category = Category.SECURITY, - priority = 5, - severity = Severity.WARNING, - implementation = Implementation( - RegisterReceiverFlagDetector::class.java, - Scope.JAVA_FILE_SCOPE - ) - ) - - val PROTECTED_BROADCASTS = listOf( - "android.intent.action.SCREEN_OFF", - "android.intent.action.SCREEN_ON", - "android.intent.action.USER_PRESENT", - "android.intent.action.TIME_SET", - "android.intent.action.TIME_TICK", - "android.intent.action.TIMEZONE_CHANGED", - "android.intent.action.DATE_CHANGED", - "android.intent.action.PRE_BOOT_COMPLETED", - "android.intent.action.BOOT_COMPLETED", - "android.intent.action.PACKAGE_INSTALL", - "android.intent.action.PACKAGE_ADDED", - "android.intent.action.PACKAGE_REPLACED", - "android.intent.action.MY_PACKAGE_REPLACED", - "android.intent.action.PACKAGE_REMOVED", - "android.intent.action.PACKAGE_REMOVED_INTERNAL", - "android.intent.action.PACKAGE_FULLY_REMOVED", - "android.intent.action.PACKAGE_CHANGED", - "android.intent.action.PACKAGE_FULLY_LOADED", - "android.intent.action.PACKAGE_ENABLE_ROLLBACK", - "android.intent.action.CANCEL_ENABLE_ROLLBACK", - "android.intent.action.ROLLBACK_COMMITTED", - "android.intent.action.PACKAGE_RESTARTED", - "android.intent.action.PACKAGE_DATA_CLEARED", - "android.intent.action.PACKAGE_FIRST_LAUNCH", - "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION", - "android.intent.action.PACKAGE_NEEDS_VERIFICATION", - "android.intent.action.PACKAGE_VERIFIED", - "android.intent.action.PACKAGES_SUSPENDED", - "android.intent.action.PACKAGES_UNSUSPENDED", - "android.intent.action.PACKAGES_SUSPENSION_CHANGED", - "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY", - "android.intent.action.DISTRACTING_PACKAGES_CHANGED", - "android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED", - "android.intent.action.UID_REMOVED", - "android.intent.action.QUERY_PACKAGE_RESTART", - "android.intent.action.CONFIGURATION_CHANGED", - "android.intent.action.SPLIT_CONFIGURATION_CHANGED", - "android.intent.action.LOCALE_CHANGED", - "android.intent.action.APPLICATION_LOCALE_CHANGED", - "android.intent.action.BATTERY_CHANGED", - "android.intent.action.BATTERY_LEVEL_CHANGED", - "android.intent.action.BATTERY_LOW", - "android.intent.action.BATTERY_OKAY", - "android.intent.action.ACTION_POWER_CONNECTED", - "android.intent.action.ACTION_POWER_DISCONNECTED", - "android.intent.action.ACTION_SHUTDOWN", - "android.intent.action.CHARGING", - "android.intent.action.DISCHARGING", - "android.intent.action.DEVICE_STORAGE_LOW", - "android.intent.action.DEVICE_STORAGE_OK", - "android.intent.action.DEVICE_STORAGE_FULL", - "android.intent.action.DEVICE_STORAGE_NOT_FULL", - "android.intent.action.NEW_OUTGOING_CALL", - "android.intent.action.REBOOT", - "android.intent.action.DOCK_EVENT", - "android.intent.action.THERMAL_EVENT", - "android.intent.action.MASTER_CLEAR_NOTIFICATION", - "android.intent.action.USER_ADDED", - "android.intent.action.USER_REMOVED", - "android.intent.action.USER_STARTING", - "android.intent.action.USER_STARTED", - "android.intent.action.USER_STOPPING", - "android.intent.action.USER_STOPPED", - "android.intent.action.USER_BACKGROUND", - "android.intent.action.USER_FOREGROUND", - "android.intent.action.USER_SWITCHED", - "android.intent.action.USER_INITIALIZE", - "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION", - "android.intent.action.DOMAINS_NEED_VERIFICATION", - "android.intent.action.OVERLAY_ADDED", - "android.intent.action.OVERLAY_CHANGED", - "android.intent.action.OVERLAY_REMOVED", - "android.intent.action.OVERLAY_PRIORITY_CHANGED", - "android.intent.action.MY_PACKAGE_SUSPENDED", - "android.intent.action.MY_PACKAGE_UNSUSPENDED", - "android.os.action.POWER_SAVE_MODE_CHANGED", - "android.os.action.DEVICE_IDLE_MODE_CHANGED", - "android.os.action.POWER_SAVE_WHITELIST_CHANGED", - "android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED", - "android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL", - "android.os.action.LOW_POWER_STANDBY_ENABLED_CHANGED", - "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED", - "android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED", - "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL", - "android.app.action.ENTER_CAR_MODE", - "android.app.action.EXIT_CAR_MODE", - "android.app.action.ENTER_CAR_MODE_PRIORITIZED", - "android.app.action.EXIT_CAR_MODE_PRIORITIZED", - "android.app.action.ENTER_DESK_MODE", - "android.app.action.EXIT_DESK_MODE", - "android.app.action.NEXT_ALARM_CLOCK_CHANGED", - "android.app.action.USER_ADDED", - "android.app.action.USER_REMOVED", - "android.app.action.USER_STARTED", - "android.app.action.USER_STOPPED", - "android.app.action.USER_SWITCHED", - "android.app.action.BUGREPORT_SHARING_DECLINED", - "android.app.action.BUGREPORT_FAILED", - "android.app.action.BUGREPORT_SHARE", - "android.app.action.SHOW_DEVICE_MONITORING_DIALOG", - "android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED", - "android.intent.action.INCIDENT_REPORT_READY", - "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS", - "android.appwidget.action.APPWIDGET_DELETED", - "android.appwidget.action.APPWIDGET_DISABLED", - "android.appwidget.action.APPWIDGET_ENABLED", - "android.appwidget.action.APPWIDGET_HOST_RESTORED", - "android.appwidget.action.APPWIDGET_RESTORED", - "android.appwidget.action.APPWIDGET_ENABLE_AND_UPDATE", - "android.os.action.SETTING_RESTORED", - "android.app.backup.intent.CLEAR", - "android.app.backup.intent.INIT", - "android.bluetooth.intent.DISCOVERABLE_TIMEOUT", - "android.bluetooth.adapter.action.STATE_CHANGED", - "android.bluetooth.adapter.action.SCAN_MODE_CHANGED", - "android.bluetooth.adapter.action.DISCOVERY_STARTED", - "android.bluetooth.adapter.action.DISCOVERY_FINISHED", - "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED", - "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED", - "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.device.action.UUID", - "android.bluetooth.device.action.MAS_INSTANCE", - "android.bluetooth.device.action.ALIAS_CHANGED", - "android.bluetooth.device.action.FOUND", - "android.bluetooth.device.action.CLASS_CHANGED", - "android.bluetooth.device.action.ACL_CONNECTED", - "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED", - "android.bluetooth.device.action.ACL_DISCONNECTED", - "android.bluetooth.device.action.NAME_CHANGED", - "android.bluetooth.device.action.BOND_STATE_CHANGED", - "android.bluetooth.device.action.NAME_FAILED", - "android.bluetooth.device.action.PAIRING_REQUEST", - "android.bluetooth.device.action.PAIRING_CANCEL", - "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY", - "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL", - "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST", - "android.bluetooth.device.action.SDP_RECORD", - "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED", - "android.bluetooth.devicepicker.action.LAUNCH", - "android.bluetooth.devicepicker.action.DEVICE_SELECTED", - "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED", - "android.bluetooth.action.CSIS_DEVICE_AVAILABLE", - "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE", - "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED", - "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY", - "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY", - "android.bluetooth.mapmce.profile.action.MESSAGE_READ_STATUS_CHANGED", - "android.bluetooth.mapmce.profile.action.MESSAGE_DELETED_STATUS_CHANGED", - "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED", - "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED", - "android.bluetooth.action.LE_AUDIO_CONF_CHANGED", - "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED", - "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED", - "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED", - "android.btopp.intent.action.INCOMING_FILE_NOTIFICATION", - "android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT", - "android.btopp.intent.action.LIST", - "android.btopp.intent.action.OPEN_OUTBOUND", - "android.btopp.intent.action.HIDE_COMPLETE", - "android.btopp.intent.action.CONFIRM", - "android.btopp.intent.action.HIDE", - "android.btopp.intent.action.RETRY", - "android.btopp.intent.action.OPEN", - "android.btopp.intent.action.OPEN_INBOUND", - "android.btopp.intent.action.TRANSFER_COMPLETE", - "android.btopp.intent.action.ACCEPT", - "android.btopp.intent.action.DECLINE", - "com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN", - "com.android.bluetooth.pbap.authchall", - "com.android.bluetooth.pbap.userconfirmtimeout", - "com.android.bluetooth.pbap.authresponse", - "com.android.bluetooth.pbap.authcancelled", - "com.android.bluetooth.sap.USER_CONFIRM_TIMEOUT", - "com.android.bluetooth.sap.action.DISCONNECT_ACTION", - "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED", - "android.hardware.usb.action.USB_STATE", - "android.hardware.usb.action.USB_PORT_CHANGED", - "android.hardware.usb.action.USB_ACCESSORY_ATTACHED", - "android.hardware.usb.action.USB_ACCESSORY_DETACHED", - "android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE", - "android.hardware.usb.action.USB_DEVICE_ATTACHED", - "android.hardware.usb.action.USB_DEVICE_DETACHED", - "android.intent.action.HEADSET_PLUG", - "android.media.action.HDMI_AUDIO_PLUG", - "android.media.action.MICROPHONE_MUTE_CHANGED", - "android.media.action.SPEAKERPHONE_STATE_CHANGED", - "android.media.AUDIO_BECOMING_NOISY", - "android.media.RINGER_MODE_CHANGED", - "android.media.VIBRATE_SETTING_CHANGED", - "android.media.VOLUME_CHANGED_ACTION", - "android.media.MASTER_VOLUME_CHANGED_ACTION", - "android.media.MASTER_MUTE_CHANGED_ACTION", - "android.media.MASTER_MONO_CHANGED_ACTION", - "android.media.MASTER_BALANCE_CHANGED_ACTION", - "android.media.SCO_AUDIO_STATE_CHANGED", - "android.media.ACTION_SCO_AUDIO_STATE_UPDATED", - "android.intent.action.MEDIA_REMOVED", - "android.intent.action.MEDIA_UNMOUNTED", - "android.intent.action.MEDIA_CHECKING", - "android.intent.action.MEDIA_NOFS", - "android.intent.action.MEDIA_MOUNTED", - "android.intent.action.MEDIA_SHARED", - "android.intent.action.MEDIA_UNSHARED", - "android.intent.action.MEDIA_BAD_REMOVAL", - "android.intent.action.MEDIA_UNMOUNTABLE", - "android.intent.action.MEDIA_EJECT", - "android.net.conn.CAPTIVE_PORTAL", - "android.net.conn.CONNECTIVITY_CHANGE", - "android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE", - "android.net.conn.DATA_ACTIVITY_CHANGE", - "android.net.conn.RESTRICT_BACKGROUND_CHANGED", - "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED", - "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED", - "android.net.nsd.STATE_CHANGED", - "android.se.omapi.action.SECURE_ELEMENT_STATE_CHANGED", - "android.nfc.action.ADAPTER_STATE_CHANGED", - "android.nfc.action.PREFERRED_PAYMENT_CHANGED", - "android.nfc.action.TRANSACTION_DETECTED", - "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC", - "com.android.nfc.action.LLCP_UP", - "com.android.nfc.action.LLCP_DOWN", - "com.android.nfc.cardemulation.action.CLOSE_TAP_DIALOG", - "com.android.nfc.handover.action.ALLOW_CONNECT", - "com.android.nfc.handover.action.DENY_CONNECT", - "com.android.nfc.handover.action.TIMEOUT_CONNECT", - "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED", - "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED", - "com.android.nfc_extras.action.AID_SELECTED", - "android.btopp.intent.action.WHITELIST_DEVICE", - "android.btopp.intent.action.STOP_HANDOVER_TRANSFER", - "android.nfc.handover.intent.action.HANDOVER_SEND", - "android.nfc.handover.intent.action.HANDOVER_SEND_MULTIPLE", - "com.android.nfc.handover.action.CANCEL_HANDOVER_TRANSFER", - "android.net.action.CLEAR_DNS_CACHE", - "android.intent.action.PROXY_CHANGE", - "android.os.UpdateLock.UPDATE_LOCK_CHANGED", - "android.intent.action.DREAMING_STARTED", - "android.intent.action.DREAMING_STOPPED", - "android.intent.action.ANY_DATA_STATE", - "com.android.server.stats.action.TRIGGER_COLLECTION", - "com.android.server.WifiManager.action.START_SCAN", - "com.android.server.WifiManager.action.START_PNO", - "com.android.server.WifiManager.action.DELAYED_DRIVER_STOP", - "com.android.server.WifiManager.action.DEVICE_IDLE", - "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED", - "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED", - "com.android.internal.action.EUICC_FACTORY_RESET", - "com.android.server.usb.ACTION_OPEN_IN_APPS", - "com.android.server.am.DELETE_DUMPHEAP", - "com.android.server.net.action.SNOOZE_WARNING", - "com.android.server.net.action.SNOOZE_RAPID", - "com.android.server.wifi.ACTION_SHOW_SET_RANDOMIZATION_DETAILS", - "com.android.server.wifi.action.NetworkSuggestion.USER_ALLOWED_APP", - "com.android.server.wifi.action.NetworkSuggestion.USER_DISALLOWED_APP", - "com.android.server.wifi.action.NetworkSuggestion.USER_DISMISSED", - "com.android.server.wifi.action.CarrierNetwork.USER_ALLOWED_CARRIER", - "com.android.server.wifi.action.CarrierNetwork.USER_DISALLOWED_CARRIER", - "com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED", - "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION", - "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK", - "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK", - "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE", - "com.android.server.wifi.wakeup.DISMISS_NOTIFICATION", - "com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES", - "com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS", - "com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE", - "android.net.wifi.WIFI_STATE_CHANGED", - "android.net.wifi.WIFI_AP_STATE_CHANGED", - "android.net.wifi.WIFI_CREDENTIAL_CHANGED", - "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED", - "android.net.wifi.aware.action.WIFI_AWARE_RESOURCE_CHANGED", - "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED", - "android.net.wifi.SCAN_RESULTS", - "android.net.wifi.RSSI_CHANGED", - "android.net.wifi.STATE_CHANGE", - "android.net.wifi.LINK_CONFIGURATION_CHANGED", - "android.net.wifi.CONFIGURED_NETWORKS_CHANGE", - "android.net.wifi.action.NETWORK_SETTINGS_RESET", - "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT", - "android.net.wifi.action.PASSPOINT_ICON", - "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST", - "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION", - "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW", - "android.net.wifi.action.REFRESH_USER_PROVISIONING", - "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION", - "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED", - "android.net.wifi.supplicant.CONNECTION_CHANGE", - "android.net.wifi.supplicant.STATE_CHANGE", - "android.net.wifi.p2p.STATE_CHANGED", - "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE", - "android.net.wifi.p2p.THIS_DEVICE_CHANGED", - "android.net.wifi.p2p.PEERS_CHANGED", - "android.net.wifi.p2p.CONNECTION_STATE_CHANGE", - "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED", - "android.net.conn.TETHER_STATE_CHANGED", - "android.net.conn.INET_CONDITION_ACTION", - "android.net.conn.NETWORK_CONDITIONS_MEASURED", - "android.net.scoring.SCORE_NETWORKS", - "android.net.scoring.SCORER_CHANGED", - "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE", - "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE", - "android.intent.action.AIRPLANE_MODE", - "android.intent.action.ADVANCED_SETTINGS", - "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED", - "com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES", - "com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT", - "com.android.server.adb.WIRELESS_DEBUG_STATUS", - "android.intent.action.ACTION_IDLE_MAINTENANCE_START", - "android.intent.action.ACTION_IDLE_MAINTENANCE_END", - "com.android.server.ACTION_TRIGGER_IDLE", - "android.intent.action.HDMI_PLUGGED", - "android.intent.action.PHONE_STATE", - "android.intent.action.SUB_DEFAULT_CHANGED", - "android.location.PROVIDERS_CHANGED", - "android.location.MODE_CHANGED", - "android.location.action.GNSS_CAPABILITIES_CHANGED", - "android.net.proxy.PAC_REFRESH", - "android.telecom.action.DEFAULT_DIALER_CHANGED", - "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED", - "android.provider.action.SMS_MMS_DB_CREATED", - "android.provider.action.SMS_MMS_DB_LOST", - "android.intent.action.CONTENT_CHANGED", - "android.provider.Telephony.MMS_DOWNLOADED", - "android.content.action.PERMISSION_RESPONSE_RECEIVED", - "android.content.action.REQUEST_PERMISSION", - "android.nfc.handover.intent.action.HANDOVER_STARTED", - "android.nfc.handover.intent.action.TRANSFER_DONE", - "android.nfc.handover.intent.action.TRANSFER_PROGRESS", - "android.nfc.handover.intent.action.TRANSFER_DONE", - "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED", - "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED", - "android.intent.action.ACTION_SET_RADIO_CAPABILITY_DONE", - "android.intent.action.ACTION_SET_RADIO_CAPABILITY_FAILED", - "android.internal.policy.action.BURN_IN_PROTECTION", - "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED", - "android.app.action.RESET_PROTECTION_POLICY_CHANGED", - "android.app.action.DEVICE_OWNER_CHANGED", - "android.app.action.MANAGED_USER_CREATED", - "android.intent.action.ANR", - "android.intent.action.CALL", - "android.intent.action.CALL_PRIVILEGED", - "android.intent.action.DROPBOX_ENTRY_ADDED", - "android.intent.action.INPUT_METHOD_CHANGED", - "android.intent.action.internal_sim_state_changed", - "android.intent.action.LOCKED_BOOT_COMPLETED", - "android.intent.action.PRECISE_CALL_STATE", - "android.intent.action.SUBSCRIPTION_PHONE_STATE", - "android.intent.action.USER_INFO_CHANGED", - "android.intent.action.USER_UNLOCKED", - "android.intent.action.WALLPAPER_CHANGED", - "android.app.action.DEVICE_POLICY_MANAGER_STATE_CHANGED", - "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS", - "android.app.action.DEVICE_ADMIN_DISABLED", - "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED", - "android.app.action.DEVICE_ADMIN_ENABLED", - "android.app.action.LOCK_TASK_ENTERING", - "android.app.action.LOCK_TASK_EXITING", - "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE", - "android.app.action.ACTION_PASSWORD_CHANGED", - "android.app.action.ACTION_PASSWORD_EXPIRING", - "android.app.action.ACTION_PASSWORD_FAILED", - "android.app.action.ACTION_PASSWORD_SUCCEEDED", - "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION", - "com.android.server.ACTION_PROFILE_OFF_DEADLINE", - "com.android.server.ACTION_TURN_PROFILE_ON_NOTIFICATION", - "android.intent.action.MANAGED_PROFILE_ADDED", - "android.intent.action.MANAGED_PROFILE_UNLOCKED", - "android.intent.action.MANAGED_PROFILE_REMOVED", - "android.app.action.MANAGED_PROFILE_PROVISIONED", - "android.bluetooth.adapter.action.BLE_STATE_CHANGED", - "com.android.bluetooth.map.USER_CONFIRM_TIMEOUT", - "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT", - "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY", - "android.content.jobscheduler.JOB_DELAY_EXPIRED", - "android.content.syncmanager.SYNC_ALARM", - "android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION", - "android.media.STREAM_DEVICES_CHANGED_ACTION", - "android.media.STREAM_MUTE_CHANGED_ACTION", - "android.net.sip.SIP_SERVICE_UP", - "android.nfc.action.ADAPTER_STATE_CHANGED", - "android.os.action.CHARGING", - "android.os.action.DISCHARGING", - "android.search.action.SEARCHABLES_CHANGED", - "android.security.STORAGE_CHANGED", - "android.security.action.TRUST_STORE_CHANGED", - "android.security.action.KEYCHAIN_CHANGED", - "android.security.action.KEY_ACCESS_CHANGED", - "android.telecom.action.NUISANCE_CALL_STATUS_CHANGED", - "android.telecom.action.PHONE_ACCOUNT_REGISTERED", - "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED", - "android.telecom.action.POST_CALL", - "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION", - "android.telephony.action.CARRIER_CONFIG_CHANGED", - "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED", - "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED", - "android.telephony.action.SECRET_CODE", - "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION", - "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED", - "com.android.bluetooth.btservice.action.ALARM_WAKEUP", - "com.android.server.action.NETWORK_STATS_POLL", - "com.android.server.action.NETWORK_STATS_UPDATED", - "com.android.server.timedetector.NetworkTimeUpdateService.action.POLL", - "com.android.server.telecom.intent.action.CALLS_ADD_ENTRY", - "com.android.settings.location.MODE_CHANGING", - "com.android.settings.bluetooth.ACTION_DISMISS_PAIRING", - "com.android.settings.network.DELETE_SUBSCRIPTION", - "com.android.settings.network.SWITCH_TO_SUBSCRIPTION", - "com.android.settings.wifi.action.NETWORK_REQUEST", - "NotificationManagerService.TIMEOUT", - "NotificationHistoryDatabase.CLEANUP", - "ScheduleConditionProvider.EVALUATE", - "EventConditionProvider.EVALUATE", - "SnoozeHelper.EVALUATE", - "wifi_scan_available", - "action.cne.started", - "android.content.jobscheduler.JOB_DEADLINE_EXPIRED", - "android.intent.action.ACTION_UNSOL_RESPONSE_OEM_HOOK_RAW", - "android.net.conn.CONNECTIVITY_CHANGE_SUPL", - "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED", - "android.os.storage.action.VOLUME_STATE_CHANGED", - "android.os.storage.action.DISK_SCANNED", - "com.android.server.action.UPDATE_TWILIGHT_STATE", - "com.android.server.action.RESET_TWILIGHT_AUTO", - "com.android.server.device_idle.STEP_IDLE_STATE", - "com.android.server.device_idle.STEP_LIGHT_IDLE_STATE", - "com.android.server.Wifi.action.TOGGLE_PNO", - "intent.action.ACTION_RF_BAND_INFO", - "android.intent.action.MEDIA_RESOURCE_GRANTED", - "android.app.action.NETWORK_LOGS_AVAILABLE", - "android.app.action.SECURITY_LOGS_AVAILABLE", - "android.app.action.COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED", - "android.app.action.INTERRUPTION_FILTER_CHANGED", - "android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL", - "android.app.action.NOTIFICATION_POLICY_CHANGED", - "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED", - "android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED", - "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED", - "android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED", - "android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED", - "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED", - "android.app.action.APP_BLOCK_STATE_CHANGED", - "android.permission.GET_APP_GRANTED_URI_PERMISSIONS", - "android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS", - "android.intent.action.DYNAMIC_SENSOR_CHANGED", - "android.accounts.LOGIN_ACCOUNTS_CHANGED", - "android.accounts.action.ACCOUNT_REMOVED", - "android.accounts.action.VISIBLE_ACCOUNTS_CHANGED", - "com.android.sync.SYNC_CONN_STATUS_CHANGED", - "android.net.sip.action.SIP_INCOMING_CALL", - "com.android.phone.SIP_ADD_PHONE", - "android.net.sip.action.SIP_REMOVE_PROFILE", - "android.net.sip.action.SIP_SERVICE_UP", - "android.net.sip.action.SIP_CALL_OPTION_CHANGED", - "android.net.sip.action.START_SIP", - "android.bluetooth.adapter.action.BLE_ACL_CONNECTED", - "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED", - "android.bluetooth.input.profile.action.HANDSHAKE", - "android.bluetooth.input.profile.action.REPORT", - "android.intent.action.TWILIGHT_CHANGED", - "com.android.server.fingerprint.ACTION_LOCKOUT_RESET", - "android.net.wifi.PASSPOINT_ICON_RECEIVED", - "com.android.server.notification.CountdownConditionProvider", - "android.server.notification.action.ENABLE_NAS", - "android.server.notification.action.DISABLE_NAS", - "android.server.notification.action.LEARNMORE_NAS", - "com.android.internal.location.ALARM_WAKEUP", - "com.android.internal.location.ALARM_TIMEOUT", - "android.intent.action.GLOBAL_BUTTON", - "android.intent.action.MANAGED_PROFILE_AVAILABLE", - "android.intent.action.MANAGED_PROFILE_UNAVAILABLE", - "com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK", - "android.intent.action.PROFILE_ACCESSIBLE", - "android.intent.action.PROFILE_INACCESSIBLE", - "com.android.server.retaildemo.ACTION_RESET_DEMO", - "android.intent.action.DEVICE_LOCKED_CHANGED", - "com.android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED", - "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED", - "com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION", - "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED", - "android.content.pm.action.SESSION_COMMITTED", - "android.os.action.USER_RESTRICTIONS_CHANGED", - "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT", - "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED", - "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED", - "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED", - "com.android.server.inputmethod.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER", - "com.android.intent.action.timezone.RULES_UPDATE_OPERATION", - "com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK", - "android.intent.action.GET_RESTRICTION_ENTRIES", - "android.telephony.euicc.action.OTA_STATUS_CHANGED", - "android.app.action.PROFILE_OWNER_CHANGED", - "android.app.action.TRANSFER_OWNERSHIP_COMPLETE", - "android.app.action.AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE", - "android.app.action.STATSD_STARTED", - "com.android.server.biometrics.fingerprint.ACTION_LOCKOUT_RESET", - "com.android.server.biometrics.face.ACTION_LOCKOUT_RESET", - "android.intent.action.DOCK_IDLE", - "android.intent.action.DOCK_ACTIVE", - "android.content.pm.action.SESSION_UPDATED", - "android.settings.action.GRAYSCALE_CHANGED", - "com.android.server.jobscheduler.GARAGE_MODE_ON", - "com.android.server.jobscheduler.GARAGE_MODE_OFF", - "com.android.server.jobscheduler.FORCE_IDLE", - "com.android.server.jobscheduler.UNFORCE_IDLE", - "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL", - "android.intent.action.DEVICE_CUSTOMIZATION_READY", - "android.app.action.RESET_PROTECTION_POLICY_CHANGED", - "com.android.internal.intent.action.BUGREPORT_REQUESTED", - "android.scheduling.action.REBOOT_READY", - "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED", - "android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED", - "android.app.action.SHOW_NEW_USER_DISCLAIMER", - "android.telecom.action.CURRENT_TTY_MODE_CHANGED", - "android.intent.action.SERVICE_STATE", - "android.intent.action.RADIO_TECHNOLOGY", - "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED", - "android.intent.action.EMERGENCY_CALL_STATE_CHANGED", - "android.intent.action.SIG_STR", - "android.intent.action.ANY_DATA_STATE", - "android.intent.action.DATA_STALL_DETECTED", - "android.intent.action.SIM_STATE_CHANGED", - "android.intent.action.USER_ACTIVITY_NOTIFICATION", - "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS", - "android.intent.action.ACTION_MDN_STATE_CHANGED", - "android.telephony.action.SERVICE_PROVIDERS_UPDATED", - "android.provider.Telephony.SIM_FULL", - "com.android.internal.telephony.carrier_key_download_alarm", - "com.android.internal.telephony.data-restart-trysetup", - "com.android.internal.telephony.data-stall", - "com.android.internal.telephony.provisioning_apn_alarm", - "android.intent.action.DATA_SMS_RECEIVED", - "android.provider.Telephony.SMS_RECEIVED", - "android.provider.Telephony.SMS_DELIVER", - "android.provider.Telephony.SMS_REJECTED", - "android.provider.Telephony.WAP_PUSH_DELIVER", - "android.provider.Telephony.WAP_PUSH_RECEIVED", - "android.provider.Telephony.SMS_CB_RECEIVED", - "android.provider.action.SMS_EMERGENCY_CB_RECEIVED", - "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED", - "android.provider.Telephony.SECRET_CODE", - "com.android.internal.stk.command", - "com.android.internal.stk.session_end", - "com.android.internal.stk.icc_status_change", - "com.android.internal.stk.alpha_notify", - "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED", - "com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED", - "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE", - "com.android.internal.telephony.CARRIER_SIGNAL_RESET", - "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE", - "com.android.internal.telephony.PROVISION", - "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED", - "com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED", - "com.android.intent.isim_refresh", - "com.android.ims.ACTION_RCS_SERVICE_AVAILABLE", - "com.android.ims.ACTION_RCS_SERVICE_UNAVAILABLE", - "com.android.ims.ACTION_RCS_SERVICE_DIED", - "com.android.ims.ACTION_PRESENCE_CHANGED", - "com.android.ims.ACTION_PUBLISH_STATUS_CHANGED", - "com.android.ims.IMS_SERVICE_UP", - "com.android.ims.IMS_SERVICE_DOWN", - "com.android.ims.IMS_INCOMING_CALL", - "com.android.ims.internal.uce.UCE_SERVICE_UP", - "com.android.ims.internal.uce.UCE_SERVICE_DOWN", - "com.android.imsconnection.DISCONNECTED", - "com.android.intent.action.IMS_FEATURE_CHANGED", - "com.android.intent.action.IMS_CONFIG_CHANGED", - "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR", - "com.android.phone.vvm.omtp.sms.REQUEST_SENT", - "com.android.phone.vvm.ACTION_VISUAL_VOICEMAIL_SERVICE_EVENT", - "com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED", - "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO", - "com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD", - "com.android.internal.telephony.action.COUNTRY_OVERRIDE", - "com.android.internal.telephony.OPEN_DEFAULT_SMS_APP", - "com.android.internal.telephony.ACTION_TEST_OVERRIDE_CARRIER_ID", - "android.telephony.action.SIM_CARD_STATE_CHANGED", - "android.telephony.action.SIM_APPLICATION_STATE_CHANGED", - "android.telephony.action.SIM_SLOT_STATUS_CHANGED", - "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED", - "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED", - "android.telephony.action.TOGGLE_PROVISION", - "android.telephony.action.NETWORK_COUNTRY_CHANGED", - "android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED", - "android.telephony.action.MULTI_SIM_CONFIG_CHANGED", - "android.telephony.action.CARRIER_SIGNAL_RESET", - "android.telephony.action.CARRIER_SIGNAL_PCO_VALUE", - "android.telephony.action.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE", - "android.telephony.action.CARRIER_SIGNAL_REDIRECTED", - "android.telephony.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED", - "com.android.phone.settings.CARRIER_PROVISIONING", - "com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING", - "com.android.internal.telephony.ACTION_VOWIFI_ENABLED", - "android.telephony.action.ANOMALY_REPORTED", - "android.intent.action.SUBSCRIPTION_INFO_RECORD_ADDED", - "android.intent.action.ACTION_MANAGED_ROAMING_IND", - "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE", - "android.safetycenter.action.REFRESH_SAFETY_SOURCES", - "android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED", - "android.app.action.DEVICE_POLICY_RESOURCE_UPDATED", - "android.intent.action.SHOW_FOREGROUND_SERVICE_MANAGER", - "android.service.autofill.action.DELAYED_FILL", - "android.app.action.PROVISIONING_COMPLETED", - "android.app.action.LOST_MODE_LOCATION_UPDATE", - "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED", - "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT", - "android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED", - "android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED", - "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED", - "android.bluetooth.headsetclient.profile.action.AG_EVENT", - "android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED", - "android.bluetooth.headsetclient.profile.action.RESULT", - "android.bluetooth.headsetclient.profile.action.LAST_VTAG", - "android.bluetooth.headsetclient.profile.action.NETWORK_SERVICE_STATE_CHANGED", - "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED", - "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED", - "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED", - "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED", - "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED", - "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED", - "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED", - "android.bluetooth.avrcp-controller.profile.action.BROWSE_CONNECTION_STATE_CHANGED", - "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.avrcp-controller.profile.action.FOLDER_LIST", - "android.bluetooth.avrcp-controller.profile.action.TRACK_EVENT", - "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED", - "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED", - "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS", - "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED", - "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT", - "com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY", - "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED", - "android.bluetooth.action.TETHERING_STATE_CHANGED", - "com.android.internal.action.EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS", - "android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED", - "com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION", - "com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" - ) - } -} diff --git a/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt b/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt deleted file mode 100644 index 7c0ebca4ec1e..000000000000 --- a/tools/lint/framework/checks/src/test/java/com/google/android/lint/RegisterReceiverFlagDetectorTest.kt +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.lint - -import com.android.tools.lint.checks.infrastructure.LintDetectorTest -import com.android.tools.lint.checks.infrastructure.TestFile -import com.android.tools.lint.checks.infrastructure.TestLintTask -import com.android.tools.lint.detector.api.Detector -import com.android.tools.lint.detector.api.Issue - -@Suppress("UnstableApiUsage") -class RegisterReceiverFlagDetectorTest : LintDetectorTest() { - - override fun getDetector(): Detector = RegisterReceiverFlagDetector() - - override fun getIssues(): List<Issue> = listOf( - RegisterReceiverFlagDetector.ISSUE_RECEIVER_EXPORTED_FLAG - ) - - override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) - - fun testProtectedBroadcast() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - context.registerReceiver(receiver, filter); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - fun testProtectedBroadcastCreate() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = - IntentFilter.create(Intent.ACTION_BATTERY_CHANGED, "foo/bar"); - context.registerReceiver(receiver, filter); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - fun testMultipleProtectedBroadcasts() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(Intent.ACTION_BATTERY_LOW); - filter.addAction(Intent.ACTION_BATTERY_OKAY); - context.registerReceiver(receiver, filter); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - // TODO(b/267510341): Reenable this test - // fun testSubsequentFilterModification() { - // lint().files( - // java( - // """ - // package test.pkg; - // import android.content.BroadcastReceiver; - // import android.content.Context; - // import android.content.Intent; - // import android.content.IntentFilter; - // public class TestClass1 { - // public void testMethod(Context context, BroadcastReceiver receiver) { - // IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - // filter.addAction(Intent.ACTION_BATTERY_LOW); - // filter.addAction(Intent.ACTION_BATTERY_OKAY); - // context.registerReceiver(receiver, filter); - // filter.addAction("querty"); - // context.registerReceiver(receiver, filter); - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.java:13: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - fun testNullReceiver() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context) { - IntentFilter filter = new IntentFilter("qwerty"); - context.registerReceiver(null, filter); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - fun testExportedFlagPresent() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter("qwerty"); - context.registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - fun testNotExportedFlagPresent() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter("qwerty"); - context.registerReceiver(receiver, filter, - Context.RECEIVER_NOT_EXPORTED); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - // TODO(b/267510341): Reenable this test - // fun testFlagArgumentAbsent() { - // lint().files( - // java( - // """ - // package test.pkg; - // import android.content.BroadcastReceiver; - // import android.content.Context; - // import android.content.Intent; - // import android.content.IntentFilter; - // public class TestClass1 { - // public void testMethod(Context context, BroadcastReceiver receiver) { - // IntentFilter filter = new IntentFilter("qwerty"); - // context.registerReceiver(receiver, filter); - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - // TODO(b/267510341): Reenable this test - // fun testExportedFlagsAbsent() { - // lint().files( - // java( - // """ - // package test.pkg; - // import android.content.BroadcastReceiver; - // import android.content.Context; - // import android.content.Intent; - // import android.content.IntentFilter; - // public class TestClass1 { - // public void testMethod(Context context, BroadcastReceiver receiver) { - // IntentFilter filter = new IntentFilter("qwerty"); - // context.registerReceiver(receiver, filter, 0); - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter, 0); - // ~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - fun testExportedFlagVariable() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter("qwerty"); - var flags = Context.RECEIVER_EXPORTED; - context.registerReceiver(receiver, filter, flags); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - // TODO(b/267510341): Reenable this test - // fun testUnknownFilter() { - // lint().files( - // java( - // """ - // package test.pkg; - // import android.content.BroadcastReceiver; - // import android.content.Context; - // import android.content.Intent; - // import android.content.IntentFilter; - // public class TestClass1 { - // public void testMethod(Context context, BroadcastReceiver receiver, - // IntentFilter filter) { - // context.registerReceiver(receiver, filter); - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.java:9: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - // TODO(b/267510341): Reenable this test - // fun testFilterEscapes() { - // lint().files( - // java( - // """ - // package test.pkg; - // import android.content.BroadcastReceiver; - // import android.content.Context; - // import android.content.Intent; - // import android.content.IntentFilter; - // public class TestClass1 { - // public void testMethod(Context context, BroadcastReceiver receiver) { - // IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - // updateFilter(filter); - // context.registerReceiver(receiver, filter); - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.java:10: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter); - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - fun testInlineFilter() { - lint().files( - java( - """ - package test.pkg; - import android.content.BroadcastReceiver; - import android.content.Context; - import android.content.Intent; - import android.content.IntentFilter; - public class TestClass1 { - public void testMethod(Context context, BroadcastReceiver receiver) { - context.registerReceiver(receiver, - new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); - } - } - """ - ).indented(), - *stubs - ) - .run() - .expectClean() - } - - // TODO(b/267510341): Reenable this test - // fun testInlineFilterApply() { - // lint().files( - // kotlin( - // """ - // package test.pkg - // import android.content.BroadcastReceiver - // import android.content.Context - // import android.content.Intent - // import android.content.IntentFilter - // class TestClass1 { - // fun test(context: Context, receiver: BroadcastReceiver) { - // context.registerReceiver(receiver, - // IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply { - // addAction("qwerty") - // }) - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.kt:8: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, - // ^ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - // TODO(b/267510341): Reenable this test - // fun testFilterVariableApply() { - // lint().files( - // kotlin( - // """ - // package test.pkg - // import android.content.BroadcastReceiver - // import android.content.Context - // import android.content.Intent - // import android.content.IntentFilter - // class TestClass1 { - // fun test(context: Context, receiver: BroadcastReceiver) { - // val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply { - // addAction("qwerty") - // } - // context.registerReceiver(receiver, filter) - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.kt:11: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter) - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - // TODO(b/267510341): Reenable this test - // fun testFilterVariableApply2() { - // lint().files( - // kotlin( - // """ - // package test.pkg - // import android.content.BroadcastReceiver - // import android.content.Context - // import android.content.Intent - // import android.content.IntentFilter - // class TestClass1 { - // fun test(context: Context, receiver: BroadcastReceiver) { - // val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply { - // addAction(Intent.ACTION_BATTERY_OKAY) - // } - // context.registerReceiver(receiver, filter.apply { - // addAction("qwerty") - // }) - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.kt:11: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter.apply { - // ^ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - // TODO(b/267510341): Reenable this test - // fun testFilterComplexChain() { - // lint().files( - // kotlin( - // """ - // package test.pkg - // import android.content.BroadcastReceiver - // import android.content.Context - // import android.content.Intent - // import android.content.IntentFilter - // class TestClass1 { - // fun test(context: Context, receiver: BroadcastReceiver) { - // val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED).apply { - // addAction(Intent.ACTION_BATTERY_OKAY) - // } - // val filter2 = filter - // val filter3 = filter2.apply { - // addAction(Intent.ACTION_BATTERY_LOW) - // } - // context.registerReceiver(receiver, filter3) - // val filter4 = filter3.apply { - // addAction("qwerty") - // } - // context.registerReceiver(receiver, filter4) - // } - // } - // """ - // ).indented(), - // *stubs - // ) - // .run() - // .expect(""" - // src/test/pkg/TestClass1.kt:19: Warning: Missing RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED flag [UnspecifiedRegisterReceiverFlag] - // context.registerReceiver(receiver, filter4) - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // 0 errors, 1 warnings - // """.trimIndent()) - // } - - private val broadcastReceiverStub: TestFile = java( - """ - package android.content; - public class BroadcastReceiver { - // Stub - } - """ - ).indented() - - private val contextStub: TestFile = java( - """ - package android.content; - public class Context { - public static final int RECEIVER_EXPORTED = 0x2; - public static final int RECEIVER_NOT_EXPORTED = 0x4; - @Nullable - public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver, - IntentFilter filter, - @RegisterReceiverFlags int flags); - } - """ - ).indented() - - private val intentStub: TestFile = java( - """ - package android.content; - public class Intent { - public static final String ACTION_BATTERY_CHANGED = - "android.intent.action.BATTERY_CHANGED"; - public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW"; - public static final String ACTION_BATTERY_OKAY = - "android.intent.action.BATTERY_OKAY"; - } - """ - ).indented() - - private val intentFilterStub: TestFile = java( - """ - package android.content; - public class IntentFilter { - public IntentFilter() { - // Stub - } - public IntentFilter(String action) { - // Stub - } - public IntentFilter(String action, String dataType) { - // Stub - } - public static IntentFilter create(String action, String dataType) { - return null; - } - public final void addAction(String action) { - // Stub - } - } - """ - ).indented() - - private val stubs = arrayOf(broadcastReceiverStub, contextStub, intentStub, intentFilterStub) -} |