blob: b7bc77dc97ee2edd01756a8c906254bf5c2c3bb4 [file] [log] [blame]
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.tv;
18
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.ServiceConnection;
23import android.media.tv.ITvRemoteProvider;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080024import android.os.IBinder;
25import android.os.RemoteException;
26import android.os.UserHandle;
27import android.util.Log;
28import android.util.Slog;
29
30import java.io.PrintWriter;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080031
32/**
33 * Maintains a connection to a tv remote provider service.
34 */
35final class TvRemoteProviderProxy implements ServiceConnection {
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020036 private static final String TAG = "TvRemoteProviderProxy";
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080037 private static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080038
39
40 // This should match TvRemoteProvider.ACTION_TV_REMOTE_PROVIDER
41 protected static final String SERVICE_INTERFACE =
42 "com.android.media.tv.remoteprovider.TvRemoteProvider";
43 private final Context mContext;
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020044 private final Object mLock;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080045 private final ComponentName mComponentName;
46 private final int mUserId;
47 private final int mUid;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080048
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020049 // State changes happen only in the main thread, hence no lock is needed
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080050 private boolean mRunning;
51 private boolean mBound;
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020052 private boolean mConnected;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080053
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020054 TvRemoteProviderProxy(Context context, Object lock,
Tom Macieszczakaee0bb22019-09-03 11:41:50 +020055 ComponentName componentName, int userId, int uid) {
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080056 mContext = context;
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020057 mLock = lock;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080058 mComponentName = componentName;
59 mUserId = userId;
60 mUid = uid;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080061 }
62
63 public void dump(PrintWriter pw, String prefix) {
64 pw.println(prefix + "Proxy");
65 pw.println(prefix + " mUserId=" + mUserId);
66 pw.println(prefix + " mRunning=" + mRunning);
67 pw.println(prefix + " mBound=" + mBound);
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020068 pw.println(prefix + " mConnected=" + mConnected);
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080069 }
70
71 public boolean hasComponentName(String packageName, String className) {
72 return mComponentName.getPackageName().equals(packageName)
73 && mComponentName.getClassName().equals(className);
74 }
75
76 public void start() {
77 if (!mRunning) {
78 if (DEBUG) {
79 Slog.d(TAG, this + ": Starting");
80 }
81
82 mRunning = true;
Tom Macieszczakaee0bb22019-09-03 11:41:50 +020083 bind();
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080084 }
85 }
86
87 public void stop() {
88 if (mRunning) {
89 if (DEBUG) {
90 Slog.d(TAG, this + ": Stopping");
91 }
92
93 mRunning = false;
Tom Macieszczakaee0bb22019-09-03 11:41:50 +020094 unbind();
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -080095 }
96 }
97
98 public void rebindIfDisconnected() {
Tom Macieszczak34ba4b12019-09-23 15:24:39 +020099 if (mRunning && !mConnected) {
100 unbind();
101 bind();
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800102 }
103 }
104
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800105 private void bind() {
106 if (!mBound) {
107 if (DEBUG) {
108 Slog.d(TAG, this + ": Binding");
109 }
110
111 Intent service = new Intent(SERVICE_INTERFACE);
112 service.setComponent(mComponentName);
113 try {
114 mBound = mContext.bindServiceAsUser(service, this,
115 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
116 new UserHandle(mUserId));
Tom Macieszczak34ba4b12019-09-23 15:24:39 +0200117 if (DEBUG && !mBound) {
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800118 Slog.d(TAG, this + ": Bind failed");
119 }
120 } catch (SecurityException ex) {
121 if (DEBUG) {
122 Slog.d(TAG, this + ": Bind failed", ex);
123 }
124 }
125 }
126 }
127
128 private void unbind() {
129 if (mBound) {
130 if (DEBUG) {
131 Slog.d(TAG, this + ": Unbinding");
132 }
133
134 mBound = false;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800135 mContext.unbindService(this);
136 }
137 }
138
139 @Override
140 public void onServiceConnected(ComponentName name, IBinder service) {
141 if (DEBUG) {
142 Slog.d(TAG, this + ": onServiceConnected()");
143 }
144
Tom Macieszczak34ba4b12019-09-23 15:24:39 +0200145 mConnected = true;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800146
Tom Macieszczak34ba4b12019-09-23 15:24:39 +0200147 final ITvRemoteProvider provider = ITvRemoteProvider.Stub.asInterface(service);
148 if (provider == null) {
149 Slog.e(TAG, this + ": Invalid binder");
150 return;
151 }
152
153 try {
154 provider.setRemoteServiceInputSink(new TvRemoteServiceInput(mLock, provider));
155 } catch (RemoteException e) {
156 Slog.e(TAG, this + ": Failed remote call to setRemoteServiceInputSink");
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800157 }
158 }
159
160 @Override
161 public void onServiceDisconnected(ComponentName name) {
Tom Macieszczak34ba4b12019-09-23 15:24:39 +0200162 mConnected = false;
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800163
Tom Macieszczak34ba4b12019-09-23 15:24:39 +0200164 if (DEBUG) {
165 Slog.d(TAG, this + ": onServiceDisconnected()");
Sujith Ramakrishnanb5b86c12016-01-28 16:53:16 -0800166 }
167 }
168}