Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 223060d6 authored by Joanne Chung's avatar Joanne Chung
Browse files

Bug fix: fix System crash due to NullPointerException.

If the voice interaction doesn't set RecognitionService, it may cause
NPE when it tries to get recognizer name. We don't need recognizer
name since Android 12, we delete it directly. To avoid the app does
not set RecognitionService then updating the app to earlier platform
that may cause boot loop. We add a warning log and set empty service
for voiceinteraction to let app aware the problem. Also logging and
unset the voiceinteraction service if the app try to update the app
without recognition service.

Bug: 170742278
Test: Use sample VoiceInteractionService without a RecognitionService
The system doesn't crash when choosing the sample app as the default
assistant app from Settings. And make sure the VoiceInteractionService
is unset.
Test: Install sample VoiceInteractionService with a RecognitionService
and then update it without a RecognitionService. Make sure the voice
interaction service is unset.

Change-Id: I79ab3d6449984ead0be28a94adaad57ab24d1fb9
parent a0178237
Loading
Loading
Loading
Loading
+38 −5
Original line number Diff line number Diff line
@@ -1896,17 +1896,19 @@ public class VoiceInteractionManagerService extends SystemService {

                        String serviceComponentName = serviceInfo.getComponentName()
                                .flattenToShortString();

                        String serviceRecognizerName = new ComponentName(pkg,
                                voiceInteractionServiceInfo.getRecognitionService())
                                .flattenToShortString();
                        if (voiceInteractionServiceInfo.getRecognitionService() == null) {
                            Slog.e(TAG, "The RecognitionService must be set to avoid boot "
                                    + "loop on earlier platform version. Also make sure that this "
                                    + "is a valid RecognitionService when running on Android 11 "
                                    + "or earlier.");
                            serviceComponentName = "";
                        }

                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.ASSISTANT, serviceComponentName, userId);
                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName,
                                userId);

                        return;
                    }

@@ -1947,6 +1949,29 @@ public class VoiceInteractionManagerService extends SystemService {
            }
        }

        private void resetServicesIfNoRecognitionService(ComponentName serviceComponent,
                int userHandle) {
            for (ResolveInfo resolveInfo : queryInteractorServices(userHandle,
                    serviceComponent.getPackageName())) {
                VoiceInteractionServiceInfo serviceInfo =
                        new VoiceInteractionServiceInfo(
                                mContext.getPackageManager(),
                                resolveInfo.serviceInfo);
                if (!serviceInfo.getSupportsAssist()) {
                    continue;
                }
                if (serviceInfo.getRecognitionService() == null) {
                    Slog.e(TAG, "The RecognitionService must be set to "
                            + "avoid boot loop on earlier platform version. "
                            + "Also make sure that this is a valid "
                            + "RecognitionService when running on Android 11 "
                            + "or earlier.");
                    setCurInteractor(null, userHandle);
                    resetCurAssistant(userHandle);
                }
            }
        }

        PackageMonitor mPackageMonitor = new PackageMonitor() {
            @Override
            public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
@@ -2090,6 +2115,7 @@ public class VoiceInteractionManagerService extends SystemService {

                        change = isPackageAppearing(curInteractor.getPackageName());
                        if (change != PACKAGE_UNCHANGED) {
                            resetServicesIfNoRecognitionService(curInteractor, userHandle);
                            // If current interactor is now appearing, for any reason, then
                            // restart our connection with it.
                            if (mImpl != null && curInteractor.getPackageName().equals(
@@ -2112,6 +2138,13 @@ public class VoiceInteractionManagerService extends SystemService {
                            initForUser(userHandle);
                            return;
                        }
                        change = isPackageAppearing(curAssistant.getPackageName());
                        if (change != PACKAGE_UNCHANGED) {
                            // It is possible to update Assistant without a voice interactor to one
                            // with a voice-interactor. We should make sure the recognition service
                            // is set to avoid boot loop.
                            resetServicesIfNoRecognitionService(curAssistant, userHandle);
                        }
                    }

                    // There is no interactor, so just deal with a simple recognizer.