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

Commit c09430c1 authored by Greg Kaiser's avatar Greg Kaiser
Browse files

Revert "Add a system TextToSpeech implementation that initiates ..."

Revert "Add CTS tests for TextToSpeech connection related functi..."

Revert submission 13547465-ttsproxy

Reason for revert: Setup wizard crashes due to "Service not registered: android.speech.tts.TextToSpeech$SystemConnection"
Reverted Changes:
Id4059e460:Add CTS tests for TextToSpeech connection related ...
Ie17800bae:Add a system TextToSpeech implementation that init...

Bug: 180519958
Change-Id: Ie43c485bd4d0f76f8bb0a1dc77d6d85d46ff8377
Test: Locally reverted this change and no longer see the exception in SUW we saw before.
parent 290d1119
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -4561,14 +4561,6 @@ public abstract class Context {
     */
    public static final String AUTOFILL_MANAGER_SERVICE = "autofill";

    /**
     * Official published name of the (internal) text to speech manager service.
     *
     * @hide
     * @see #getSystemService(String)
     */
    public static final String TEXT_TO_SPEECH_MANAGER_SERVICE = "texttospeech";

    /**
     * Official published name of the content capture service.
     *
+0 −29
Original line number Diff line number Diff line
/*
 * 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 android.speech.tts;

import android.speech.tts.ITextToSpeechSessionCallback;

/**
 * TextToSpeechManagerService interface. Allows opening {@link TextToSpeech} session with the
 * specified provider proxied by the system service.
 *
 * @hide
 */
oneway interface ITextToSpeechManager {
    void createSession(in String engine, in ITextToSpeechSessionCallback managerCallback);
}
+0 −33
Original line number Diff line number Diff line
/*
 * 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 android.speech.tts;

/**
 * TextToSpeech session interface. Allows to control remote TTS service session once connected.
 *
 * @see ITextToSpeechManager
 * @see ITextToSpeechSessionCallback
 *
 * {@hide}
 */
oneway interface ITextToSpeechSession {

    /**
     * Disconnects the client from the TTS provider.
     */
    void disconnect();
}
 No newline at end of file
+0 −32
Original line number Diff line number Diff line
/*
 * 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 android.speech.tts;
import android.speech.tts.ITextToSpeechSession;

/**
 * Callback interface for a session created by {@link ITextToSpeechManager} API.
 *
 * @hide
 */
oneway interface ITextToSpeechSessionCallback {

    void onConnected(in ITextToSpeechSession session, in IBinder serviceBinder);

    void onDisconnected();

    void onError(in String errorInfo);
}
 No newline at end of file
+27 −141
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Log;

@@ -52,7 +51,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.concurrent.Executor;

/**
 *
@@ -697,8 +695,6 @@ public class TextToSpeech {
        public static final String KEY_FEATURE_NETWORK_RETRIES_COUNT = "networkRetriesCount";
    }

    private static final boolean DEBUG = false;

    private final Context mContext;
    @UnsupportedAppUsage
    private Connection mConnectingServiceConnection;
@@ -720,9 +716,6 @@ public class TextToSpeech {
    private final Map<CharSequence, Uri> mUtterances;
    private final Bundle mParams = new Bundle();
    private final TtsEngines mEnginesHelper;
    private final boolean mIsSystem;
    @Nullable private final Executor mInitExecutor;

    @UnsupportedAppUsage
    private volatile String mCurrentEngine = null;

@@ -765,21 +758,8 @@ public class TextToSpeech {
     */
    public TextToSpeech(Context context, OnInitListener listener, String engine,
            String packageName, boolean useFallback) {
        this(context, /* initExecutor= */ null, listener, engine, packageName,
                useFallback, /* isSystem= */ true);
    }

    /**
     * Used internally to instantiate TextToSpeech objects.
     *
     * @hide
     */
    private TextToSpeech(Context context, @Nullable Executor initExecutor,
            OnInitListener initListener, String engine, String packageName, boolean useFallback,
            boolean isSystem) {
        mContext = context;
        mInitExecutor = initExecutor;
        mInitListener = initListener;
        mInitListener = listener;
        mRequestedEngine = engine;
        mUseFallback = useFallback;

@@ -788,9 +768,6 @@ public class TextToSpeech {
        mUtteranceProgressListener = null;

        mEnginesHelper = new TtsEngines(mContext);

        mIsSystem = isSystem;

        initTts();
    }

@@ -865,14 +842,10 @@ public class TextToSpeech {
    }

    private boolean connectToEngine(String engine) {
        Connection connection;
        if (mIsSystem) {
            connection = new SystemConnection();
        } else {
            connection = new DirectConnection();
        }

        boolean bound = connection.connect(engine);
        Connection connection = new Connection();
        Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
        intent.setPackage(engine);
        boolean bound = mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE);
        if (!bound) {
            Log.e(TAG, "Failed to bind to " + engine);
            return false;
@@ -884,20 +857,12 @@ public class TextToSpeech {
    }

    private void dispatchOnInit(int result) {
        Runnable onInitCommand = () -> {
        synchronized (mStartLock) {
            if (mInitListener != null) {
                mInitListener.onInit(result);
                mInitListener = null;
            }
        }
        };

        if (mInitExecutor != null) {
            mInitExecutor.execute(onInitCommand);
        } else {
            onInitCommand.run();
        }
    }

    private IBinder getCallerIdentity() {
@@ -2162,17 +2127,13 @@ public class TextToSpeech {
        return mEnginesHelper.getEngines();
    }

    private abstract class Connection implements ServiceConnection {
    private class Connection implements ServiceConnection {
        private ITextToSpeechService mService;

        private SetupConnectionAsyncTask mOnSetupConnectionAsyncTask;

        private boolean mEstablished;

        abstract boolean connect(String engine);

        abstract void disconnect();

        private final ITextToSpeechCallback.Stub mCallback =
                new ITextToSpeechCallback.Stub() {
                    public void onStop(String utteranceId, boolean isStarted)
@@ -2238,6 +2199,11 @@ public class TextToSpeech {
                };

        private class SetupConnectionAsyncTask extends AsyncTask<Void, Void, Integer> {
            private final ComponentName mName;

            public SetupConnectionAsyncTask(ComponentName name) {
                mName = name;
            }

            @Override
            protected Integer doInBackground(Void... params) {
@@ -2261,7 +2227,7 @@ public class TextToSpeech {
                            mParams.putString(Engine.KEY_PARAM_VOICE_NAME, defaultVoiceName);
                        }

                        Log.i(TAG, "Setting up the connection to TTS engine...");
                        Log.i(TAG, "Set up connection to " + mName);
                        return SUCCESS;
                    } catch (RemoteException re) {
                        Log.e(TAG, "Error connecting to service, setCallback() failed");
@@ -2283,11 +2249,11 @@ public class TextToSpeech {
        }

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
        public void onServiceConnected(ComponentName name, IBinder service) {
            synchronized(mStartLock) {
                mConnectingServiceConnection = null;

                Log.i(TAG, "Connected to TTS engine");
                Log.i(TAG, "Connected to " + name);

                if (mOnSetupConnectionAsyncTask != null) {
                    mOnSetupConnectionAsyncTask.cancel(false);
@@ -2297,7 +2263,7 @@ public class TextToSpeech {
                mServiceConnection = Connection.this;

                mEstablished = false;
                mOnSetupConnectionAsyncTask = new SetupConnectionAsyncTask();
                mOnSetupConnectionAsyncTask = new SetupConnectionAsyncTask(name);
                mOnSetupConnectionAsyncTask.execute();
            }
        }
@@ -2311,7 +2277,7 @@ public class TextToSpeech {
         *
         * @return true if we cancel mOnSetupConnectionAsyncTask in progress.
         */
        protected boolean clearServiceConnection() {
        private boolean clearServiceConnection() {
            synchronized(mStartLock) {
                boolean result = false;
                if (mOnSetupConnectionAsyncTask != null) {
@@ -2329,8 +2295,8 @@ public class TextToSpeech {
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.i(TAG, "Disconnected from TTS engine");
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "Asked to disconnect from " + name);
            if (clearServiceConnection()) {
                /* We need to protect against a rare case where engine
                 * dies just after successful connection - and we process onServiceDisconnected
@@ -2342,6 +2308,11 @@ public class TextToSpeech {
            }
        }

        public void disconnect() {
            mContext.unbindService(this);
            clearServiceConnection();
        }

        public boolean isEstablished() {
            return mService != null && mEstablished;
        }
@@ -2371,91 +2342,6 @@ public class TextToSpeech {
        }
    }

    // Currently all the clients are routed through the System connection. Direct connection
    // is left for debugging, testing and benchmarking purposes.
    // TODO(b/179599071): Remove direct connection once system one is fully tested.
    private class DirectConnection extends Connection {
        @Override
        boolean connect(String engine) {
            Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
            intent.setPackage(engine);
            return mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
        }

        @Override
        void disconnect() {
            mContext.unbindService(this);
            clearServiceConnection();
        }
    }

    private class SystemConnection extends Connection {

        @Nullable
        private volatile ITextToSpeechSession mSession;

        @Override
        boolean connect(String engine) {
            IBinder binder = ServiceManager.getService(Context.TEXT_TO_SPEECH_MANAGER_SERVICE);

            ITextToSpeechManager manager = ITextToSpeechManager.Stub.asInterface(binder);

            if (manager == null) {
                Log.e(TAG, "System service is not available!");
                return false;
            }

            if (DEBUG) {
                Log.d(TAG, "Connecting to engine: " + engine);
            }

            try {
                manager.createSession(engine, new ITextToSpeechSessionCallback.Stub() {
                    @Override
                    public void onConnected(ITextToSpeechSession session, IBinder serviceBinder) {
                        mSession = session;
                        onServiceConnected(
                                /* componentName= */ null,
                                serviceBinder);
                    }

                    @Override
                    public void onDisconnected() {
                        onServiceDisconnected(/* componentName= */ null);
                    }

                    @Override
                    public void onError(String errorInfo) {
                        Log.w(TAG, "System TTS connection error: " + errorInfo);
                        // The connection was not established successfully - handle as
                        // disconnection: clear the state and notify the user.
                        onServiceDisconnected(/* componentName= */ null);
                    }
                });

                return true;
            } catch (RemoteException ex) {
                Log.e(TAG, "Error communicating with the System Server: ", ex);
                throw ex.rethrowFromSystemServer();
            }
        }

        @Override
        void disconnect() {
            ITextToSpeechSession session = mSession;

            if (session != null) {
                try {
                    session.disconnect();
                } catch (RemoteException ex) {
                    Log.w(TAG, "Error disconnecting session", ex);
                }

                clearServiceConnection();
            }
        }
    }

    private interface Action<R> {
        R run(ITextToSpeechService service) throws RemoteException;
    }
Loading