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

Commit d32d96c1 authored by Sergej Salnikov's avatar Sergej Salnikov Committed by Android (Google) Code Review
Browse files

Merge "Refactor TvRemoteService."

parents 86926216 aee0bb2d
Loading
Loading
Loading
Loading
+23 −103
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.ServiceConnection;
import android.media.tv.ITvRemoteProvider;
import android.media.tv.ITvRemoteServiceInput;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -49,7 +48,6 @@ final class TvRemoteProviderProxy implements ServiceConnection {
    private final ComponentName mComponentName;
    private final int mUserId;
    private final int mUid;
    private final Handler mHandler;

    /**
     * State guarded by mLock.
@@ -65,15 +63,14 @@ final class TvRemoteProviderProxy implements ServiceConnection {
    private boolean mRunning;
    private boolean mBound;
    private Connection mActiveConnection;
    private boolean mConnectionReady;

    public TvRemoteProviderProxy(Context context, ComponentName componentName, int userId,
                                 int uid) {
    TvRemoteProviderProxy(Context context, ProviderMethods provider,
                          ComponentName componentName, int userId, int uid) {
        mContext = context;
        mProviderMethods = provider;
        mComponentName = componentName;
        mUserId = userId;
        mUid = uid;
        mHandler = new Handler();
    }

    public void dump(PrintWriter pw, String prefix) {
@@ -82,11 +79,6 @@ final class TvRemoteProviderProxy implements ServiceConnection {
        pw.println(prefix + "  mRunning=" + mRunning);
        pw.println(prefix + "  mBound=" + mBound);
        pw.println(prefix + "  mActiveConnection=" + mActiveConnection);
        pw.println(prefix + "  mConnectionReady=" + mConnectionReady);
    }

    public void setProviderSink(ProviderMethods provider) {
        mProviderMethods = provider;
    }

    public boolean hasComponentName(String packageName, String className) {
@@ -101,7 +93,7 @@ final class TvRemoteProviderProxy implements ServiceConnection {
            }

            mRunning = true;
            updateBinding();
            bind();
        }
    }

@@ -112,31 +104,19 @@ final class TvRemoteProviderProxy implements ServiceConnection {
            }

            mRunning = false;
            updateBinding();
            unbind();
        }
    }

    public void rebindIfDisconnected() {
        synchronized (mLock) {
            if (mActiveConnection == null && shouldBind()) {
            if (mActiveConnection == null && mRunning) {
                unbind();
                bind();
            }
        }
    }

    private void updateBinding() {
        if (shouldBind()) {
            bind();
        } else {
            unbind();
        }
    }

    private boolean shouldBind() {
        return mRunning;
    }

    private void bind() {
        if (!mBound) {
            if (DEBUG) {
@@ -208,47 +188,18 @@ final class TvRemoteProviderProxy implements ServiceConnection {
        disconnect();
    }


    private void onConnectionReady(Connection connection) {
        synchronized (mLock) {
            if (DEBUG) Slog.d(TAG, "onConnectionReady");
            if (mActiveConnection == connection) {
                if (DEBUG) Slog.d(TAG, "mConnectionReady = true");
                mConnectionReady = true;
            }
        }
    }

    private void onConnectionDied(Connection connection) {
        if (mActiveConnection == connection) {
            if (DEBUG) Slog.d(TAG, this + ": Service connection died");
            disconnect();
        }
    }

    private void disconnect() {
        synchronized (mLock) {
            if (mActiveConnection != null) {
                mConnectionReady = false;
                mActiveConnection.dispose();
                mActiveConnection = null;
            }
        }
    }

    // Provider helpers
    public void inputBridgeConnected(IBinder token) {
        synchronized (mLock) {
            if (DEBUG) Slog.d(TAG, this + ": inputBridgeConnected token: " + token);
            if (mConnectionReady) {
                mActiveConnection.onInputBridgeConnected(token);
            }
        }
    }

    public interface ProviderMethods {
    interface ProviderMethods {
        // InputBridge
        void openInputBridge(TvRemoteProviderProxy provider, IBinder token, String name,
        boolean openInputBridge(TvRemoteProviderProxy provider, IBinder token, String name,
                                int width, int height, int maxPointers);

        void closeInputBridge(TvRemoteProviderProxy provider, IBinder token);
@@ -267,7 +218,7 @@ final class TvRemoteProviderProxy implements ServiceConnection {
        void sendPointerSync(TvRemoteProviderProxy provider, IBinder token);
    }

    private final class Connection implements IBinder.DeathRecipient {
    private final class Connection {
        private final ITvRemoteProvider mTvRemoteProvider;
        private final RemoteServiceInputProvider mServiceInputProvider;

@@ -279,24 +230,16 @@ final class TvRemoteProviderProxy implements ServiceConnection {
        public boolean register() {
            if (DEBUG) Slog.d(TAG, "Connection::register()");
            try {
                mTvRemoteProvider.asBinder().linkToDeath(this, 0);
                mTvRemoteProvider.setRemoteServiceInputSink(mServiceInputProvider);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        onConnectionReady(Connection.this);
                    }
                });
                return true;
            } catch (RemoteException ex) {
                binderDied();
            }
                dispose();
                return false;
            }
        }

        public void dispose() {
            if (DEBUG) Slog.d(TAG, "Connection::dispose()");
            mTvRemoteProvider.asBinder().unlinkToDeath(this, 0);
            mServiceInputProvider.dispose();
        }

@@ -310,16 +253,6 @@ final class TvRemoteProviderProxy implements ServiceConnection {
            }
        }

        @Override
        public void binderDied() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    onConnectionDied(Connection.this);
                }
            });
        }

        void openInputBridge(final IBinder token, final String name, final int width,
                             final int height, final int maxPointers) {
            synchronized (mLock) {
@@ -330,9 +263,9 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.openInputBridge(TvRemoteProviderProxy.this, token,
                                    name, width, height, maxPointers);
                        if (mProviderMethods.openInputBridge(TvRemoteProviderProxy.this, token,
                                                             name, width, height, maxPointers)) {
                            onInputBridgeConnected(token);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
@@ -356,9 +289,7 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                        mProviderMethods.closeInputBridge(TvRemoteProviderProxy.this, token);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
@@ -381,9 +312,7 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                        mProviderMethods.clearInputBridge(TvRemoteProviderProxy.this, token);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
@@ -412,10 +341,7 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendKeyDown(TvRemoteProviderProxy.this, token,
                                    keyCode);
                        }
                        mProviderMethods.sendKeyDown(TvRemoteProviderProxy.this, token, keyCode);
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
@@ -438,9 +364,7 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                        mProviderMethods.sendKeyUp(TvRemoteProviderProxy.this, token, keyCode);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
@@ -463,10 +387,8 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                        mProviderMethods.sendPointerDown(TvRemoteProviderProxy.this, token,
                                pointerId, x, y);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
@@ -489,10 +411,8 @@ final class TvRemoteProviderProxy implements ServiceConnection {
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                        mProviderMethods.sendPointerUp(TvRemoteProviderProxy.this, token,
                                pointerId);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
+4 −12
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ final class TvRemoteProviderWatcher {
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);

    private final Context mContext;
    private final ProviderMethods mProvider;
    private final TvRemoteProviderProxy.ProviderMethods mProvider;
    private final Handler mHandler;
    private final PackageManager mPackageManager;
    private final ArrayList<TvRemoteProviderProxy> mProviderProxies = new ArrayList<>();
@@ -54,10 +54,10 @@ final class TvRemoteProviderWatcher {

    private boolean mRunning;

    public TvRemoteProviderWatcher(Context context, ProviderMethods provider, Handler handler) {
    TvRemoteProviderWatcher(Context context, TvRemoteProviderProxy.ProviderMethods provider) {
        mContext = context;
        mProvider = provider;
        mHandler = handler;
        mHandler = new Handler(true);
        mUserId = UserHandle.myUserId();
        mPackageManager = context.getPackageManager();
        mUnbundledServicePackage = context.getString(
@@ -116,12 +116,11 @@ final class TvRemoteProviderWatcher {
                int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
                if (sourceIndex < 0) {
                    TvRemoteProviderProxy providerProxy =
                            new TvRemoteProviderProxy(mContext,
                            new TvRemoteProviderProxy(mContext, mProvider,
                                    new ComponentName(serviceInfo.packageName, serviceInfo.name),
                                    mUserId, serviceInfo.applicationInfo.uid);
                    providerProxy.start();
                    mProviderProxies.add(targetIndex++, providerProxy);
                    mProvider.addProvider(providerProxy);
                } else if (sourceIndex >= targetIndex) {
                    TvRemoteProviderProxy provider = mProviderProxies.get(sourceIndex);
                    provider.start(); // restart the provider if needed
@@ -135,7 +134,6 @@ final class TvRemoteProviderWatcher {
        if (targetIndex < mProviderProxies.size()) {
            for (int i = mProviderProxies.size() - 1; i >= targetIndex; i--) {
                TvRemoteProviderProxy providerProxy = mProviderProxies.get(i);
                mProvider.removeProvider(providerProxy);
                mProviderProxies.remove(providerProxy);
                providerProxy.stop();
            }
@@ -212,10 +210,4 @@ final class TvRemoteProviderWatcher {
            scanPackages();
        }
    };

    public interface ProviderMethods {
        void addProvider(TvRemoteProviderProxy providerProxy);

        void removeProvider(TvRemoteProviderProxy providerProxy);
    }
}
+18 −111
Original line number Diff line number Diff line
@@ -17,11 +17,8 @@
package com.android.server.tv;

import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Looper;
import android.os.Message;
import android.util.ArrayMap;
import android.util.Slog;

@@ -29,7 +26,6 @@ import com.android.server.SystemService;
import com.android.server.Watchdog;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

/**
@@ -44,9 +40,8 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
    private static final boolean DEBUG = false;
    private static final boolean DEBUG_KEYS = false;

    private final TvRemoteProviderWatcher mWatcher;
    private Map<IBinder, UinputBridge> mBridgeMap = new ArrayMap();
    private Map<IBinder, TvRemoteProviderProxy> mProviderMap = new ArrayMap();
    private ArrayList<TvRemoteProviderProxy> mProviderList = new ArrayList<>();

    /**
     * State guarded by mLock.
@@ -60,11 +55,10 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
     */
    private final Object mLock = new Object();

    public final UserHandler mHandler;

    public TvRemoteService(Context context) {
        super(context);
        mHandler = new UserHandler(new UserProvider(TvRemoteService.this), context);
        mWatcher = new TvRemoteProviderWatcher(context,
                                               new UserProvider(TvRemoteService.this));
        Watchdog.getInstance().addMonitor(this);
    }

@@ -80,19 +74,15 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {

    @Override
    public void onBootPhase(int phase) {
        // All lifecycle methods are called from the system server's main looper thread.
        if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
            if (DEBUG) Slog.d(TAG, "PHASE_THIRD_PARTY_APPS_CAN_START");
            mHandler.sendEmptyMessage(UserHandler.MSG_START);
        }
    }

    //Outgoing calls.
    private void informInputBridgeConnected(IBinder token) {
        mHandler.obtainMessage(UserHandler.MSG_INPUT_BRIDGE_CONNECTED, 0, 0, token).sendToTarget();
            mWatcher.start(); // Also schedules the start of all providers.
        }
    }

    // Incoming calls.
    private void openInputBridgeInternalLocked(TvRemoteProviderProxy provider, final IBinder token,
    private boolean openInputBridgeInternalLocked(final IBinder token,
                                                  String name, int width, int height,
                                                  int maxPointers) {
        if (DEBUG) {
@@ -104,15 +94,11 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
            //Create a new bridge, if one does not exist already
            if (mBridgeMap.containsKey(token)) {
                if (DEBUG) Slog.d(TAG, "RemoteBridge already exists");
                // Respond back with success.
                informInputBridgeConnected(token);
                return;
                return true;
            }

            UinputBridge inputBridge = new UinputBridge(token, name, width, height, maxPointers);

            mBridgeMap.put(token, inputBridge);
            mProviderMap.put(token, provider);

            try {
                token.linkToDeath(new IBinder.DeathRecipient() {
@@ -126,15 +112,13 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
            } catch (RemoteException e) {
                if (DEBUG) Slog.d(TAG, "Token is already dead");
                closeInputBridgeInternalLocked(token);
                return;
                return false;
            }

            // Respond back with success.
            informInputBridgeConnected(token);

        } catch (IOException ioe) {
            Slog.e(TAG, "Cannot create device for " + name);
            return false;
        }
        return true;
    }

    private void closeInputBridgeInternalLocked(IBinder token) {
@@ -149,7 +133,6 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
        }

        mBridgeMap.remove(token);
        mProviderMap.remove(token);
    }

    private void clearInputBridgeInternalLocked(IBinder token) {
@@ -220,47 +203,7 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
        }
    }

    private final class UserHandler extends Handler {

        public static final int MSG_START = 1;
        public static final int MSG_INPUT_BRIDGE_CONNECTED = 2;

        private final TvRemoteProviderWatcher mWatcher;
        private boolean mRunning;

        public UserHandler(UserProvider provider, Context context) {
            super(Looper.getMainLooper(), null, true);
            mWatcher = new TvRemoteProviderWatcher(context, provider, this);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_START: {
                    start();
                    break;
                }
                case MSG_INPUT_BRIDGE_CONNECTED: {
                    IBinder token = (IBinder) msg.obj;
                    TvRemoteProviderProxy provider = mProviderMap.get(token);
                    if (provider != null) {
                        provider.inputBridgeConnected(token);
                    }
                    break;
                }
            }
        }

        private void start() {
            if (!mRunning) {
                mRunning = true;
                mWatcher.start(); // also starts all providers
            }
        }
    }

    private final class UserProvider implements TvRemoteProviderWatcher.ProviderMethods,
            TvRemoteProviderProxy.ProviderMethods {
    private final class UserProvider implements TvRemoteProviderProxy.ProviderMethods {

        private final TvRemoteService mService;

@@ -269,7 +212,7 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
        }

        @Override
        public void openInputBridge(TvRemoteProviderProxy provider, IBinder token, String name,
        public boolean openInputBridge(TvRemoteProviderProxy provider, IBinder token, String name,
                                       int width, int height, int maxPointers) {
            if (DEBUG) {
                Slog.d(TAG, "openInputBridge(), token: " + token +
@@ -278,10 +221,8 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
            }

            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.openInputBridgeInternalLocked(provider, token, name, width, height,
                            maxPointers);
                }
                return mService.openInputBridgeInternalLocked(token, name, width,
                               height, maxPointers);
            }
        }

@@ -289,21 +230,17 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
        public void closeInputBridge(TvRemoteProviderProxy provider, IBinder token) {
            if (DEBUG) Slog.d(TAG, "closeInputBridge(), token: " + token);
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.closeInputBridgeInternalLocked(token);
            }
        }
        }

        @Override
        public void clearInputBridge(TvRemoteProviderProxy provider, IBinder token) {
            if (DEBUG) Slog.d(TAG, "clearInputBridge(), token: " + token);
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.clearInputBridgeInternalLocked(token);
            }
        }
        }

        @Override
        public void sendKeyDown(TvRemoteProviderProxy provider, IBinder token, int keyCode) {
@@ -311,11 +248,9 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
                Slog.d(TAG, "sendKeyDown(), token: " + token + ", keyCode: " + keyCode);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendKeyDownInternalLocked(token, keyCode);
            }
        }
        }

        @Override
        public void sendKeyUp(TvRemoteProviderProxy provider, IBinder token, int keyCode) {
@@ -323,11 +258,9 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
                Slog.d(TAG, "sendKeyUp(), token: " + token + ", keyCode: " + keyCode);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendKeyUpInternalLocked(token, keyCode);
            }
        }
        }

        @Override
        public void sendPointerDown(TvRemoteProviderProxy provider, IBinder token, int pointerId,
@@ -336,11 +269,9 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
                Slog.d(TAG, "sendPointerDown(), token: " + token + ", pointerId: " + pointerId);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendPointerDownInternalLocked(token, pointerId, x, y);
            }
        }
        }

        @Override
        public void sendPointerUp(TvRemoteProviderProxy provider, IBinder token, int pointerId) {
@@ -348,40 +279,16 @@ public class TvRemoteService extends SystemService implements Watchdog.Monitor {
                Slog.d(TAG, "sendPointerUp(), token: " + token + ", pointerId: " + pointerId);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendPointerUpInternalLocked(token, pointerId);
            }
        }
        }

        @Override
        public void sendPointerSync(TvRemoteProviderProxy provider, IBinder token) {
            if (DEBUG_KEYS) Slog.d(TAG, "sendPointerSync(), token: " + token);
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendPointerSyncInternalLocked(token);
            }
        }
    }

        @Override
        public void addProvider(TvRemoteProviderProxy provider) {
            if (DEBUG) Slog.d(TAG, "addProvider " + provider);
            synchronized (mLock) {
                provider.setProviderSink(this);
                mProviderList.add(provider);
                Slog.d(TAG, "provider: " + provider.toString());
            }
        }

        @Override
        public void removeProvider(TvRemoteProviderProxy provider) {
            if (DEBUG) Slog.d(TAG, "removeProvider " + provider);
            synchronized (mLock) {
                if (mProviderList.remove(provider) == false) {
                    Slog.e(TAG, "Unknown provider " + provider);
                }
            }
        }
    }
}