blob: a4ea17b3c2286b1908c60af10ed449e53e1f1c22 [file] [log] [blame]
Craig Mautner4504de52013-12-20 09:06:56 -08001/*
2 * Copyright (C) 2013 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 android.app;
18
19import android.content.Context;
20import android.content.ContextWrapper;
Craig Mautner4e5b67e2014-02-07 15:30:03 -080021import android.content.IIntentSender;
Craig Mautner4504de52013-12-20 09:06:56 -080022import android.content.Intent;
Craig Mautnerdf88d732014-01-27 09:21:32 -080023import android.content.IntentSender;
Craig Mautner4504de52013-12-20 09:06:56 -080024import android.graphics.SurfaceTexture;
25import android.os.IBinder;
26import android.os.RemoteException;
27import android.util.AttributeSet;
28import android.util.DisplayMetrics;
Craig Mautner34b73df2014-01-12 21:11:08 -080029import android.util.Log;
Jeff Brown38f96e52014-02-11 14:32:56 -080030import android.view.InputDevice;
31import android.view.InputEvent;
32import android.view.MotionEvent;
Craig Mautner4504de52013-12-20 09:06:56 -080033import android.view.Surface;
34import android.view.TextureView;
35import android.view.TextureView.SurfaceTextureListener;
36import android.view.ViewGroup;
37import android.view.WindowManager;
Craig Mautnerf4c909b2014-04-17 18:39:38 -070038import dalvik.system.CloseGuard;
39
40import java.lang.ref.WeakReference;
Craig Mautner4504de52013-12-20 09:06:56 -080041
Craig Mautner95da1082014-02-24 17:54:35 -080042/** @hide */
Craig Mautner4504de52013-12-20 09:06:56 -080043public class ActivityView extends ViewGroup {
Craig Mautnerf4c909b2014-04-17 18:39:38 -070044 private static final String TAG = "ActivityView";
45 private static final boolean DEBUG = false;
Craig Mautner34b73df2014-01-12 21:11:08 -080046
Craig Mautnerf4c909b2014-04-17 18:39:38 -070047 DisplayMetrics mMetrics;
Craig Mautner4504de52013-12-20 09:06:56 -080048 private final TextureView mTextureView;
49 private IActivityContainer mActivityContainer;
50 private Activity mActivity;
Craig Mautner4504de52013-12-20 09:06:56 -080051 private int mWidth;
52 private int mHeight;
Craig Mautner34b73df2014-01-12 21:11:08 -080053 private Surface mSurface;
Craig Mautner4504de52013-12-20 09:06:56 -080054
Craig Mautner4e5b67e2014-02-07 15:30:03 -080055 // Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
56 IIntentSender mQueuedPendingIntent;
57 Intent mQueuedIntent;
58
Craig Mautnerf4c909b2014-04-17 18:39:38 -070059 private final CloseGuard mGuard = CloseGuard.get();
60
Craig Mautner4504de52013-12-20 09:06:56 -080061 public ActivityView(Context context) {
62 this(context, null);
63 }
64
65 public ActivityView(Context context, AttributeSet attrs) {
66 this(context, attrs, 0);
67 }
68
69 public ActivityView(Context context, AttributeSet attrs, int defStyle) {
70 super(context, attrs, defStyle);
71
72 while (context instanceof ContextWrapper) {
73 if (context instanceof Activity) {
74 mActivity = (Activity)context;
75 break;
76 }
77 context = ((ContextWrapper)context).getBaseContext();
78 }
79 if (mActivity == null) {
80 throw new IllegalStateException("The ActivityView's Context is not an Activity.");
81 }
82
Craig Mautnerf4c909b2014-04-17 18:39:38 -070083 try {
84 mActivityContainer = ActivityManagerNative.getDefault().createActivityContainer(
85 mActivity.getActivityToken(), new ActivityContainerCallback(this));
86 } catch (RemoteException e) {
87 throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. "
88 + e);
89 }
90
Craig Mautner4504de52013-12-20 09:06:56 -080091 mTextureView = new TextureView(context);
92 mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
93 addView(mTextureView);
Craig Mautnerf4c909b2014-04-17 18:39:38 -070094
95 WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
96 mMetrics = new DisplayMetrics();
97 wm.getDefaultDisplay().getMetrics(mMetrics);
98
99 mGuard.open("release");
100
Craig Mautner12ff7392014-02-21 21:08:00 -0800101 if (DEBUG) Log.v(TAG, "ctor()");
Craig Mautner4504de52013-12-20 09:06:56 -0800102 }
103
104 @Override
105 protected void onLayout(boolean changed, int l, int t, int r, int b) {
Griff Hazenaf745f62014-02-10 08:58:32 -0800106 mTextureView.layout(0, 0, r - l, b - t);
Craig Mautner4504de52013-12-20 09:06:56 -0800107 }
108
Jeff Brown38f96e52014-02-11 14:32:56 -0800109 private boolean injectInputEvent(InputEvent event) {
110 try {
111 return mActivityContainer != null && mActivityContainer.injectEvent(event);
112 } catch (RemoteException e) {
113 return false;
114 }
115 }
116
117 @Override
118 public boolean onTouchEvent(MotionEvent event) {
119 return injectInputEvent(event) || super.onTouchEvent(event);
120 }
121
122 @Override
123 public boolean onGenericMotionEvent(MotionEvent event) {
124 if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
125 if (injectInputEvent(event)) {
126 return true;
127 }
128 }
129 return super.onGenericMotionEvent(event);
130 }
131
Craig Mautnerdf88d732014-01-27 09:21:32 -0800132 public boolean isAttachedToDisplay() {
133 return mSurface != null;
Craig Mautner4504de52013-12-20 09:06:56 -0800134 }
135
136 public void startActivity(Intent intent) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700137 if (mActivityContainer == null) {
138 throw new IllegalStateException("Attempt to call startActivity after release");
139 }
Craig Mautner12ff7392014-02-21 21:08:00 -0800140 if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
141 (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautnerdf88d732014-01-27 09:21:32 -0800142 if (mSurface != null) {
Craig Mautner4504de52013-12-20 09:06:56 -0800143 try {
144 mActivityContainer.startActivity(intent);
145 } catch (RemoteException e) {
146 throw new IllegalStateException("ActivityView: Unable to startActivity. " + e);
147 }
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800148 } else {
149 mQueuedIntent = intent;
150 mQueuedPendingIntent = null;
151 }
152 }
153
154 private void startActivityIntentSender(IIntentSender iIntentSender) {
155 try {
156 mActivityContainer.startActivityIntentSender(iIntentSender);
157 } catch (RemoteException e) {
158 throw new IllegalStateException(
159 "ActivityView: Unable to startActivity from IntentSender. " + e);
Craig Mautner4504de52013-12-20 09:06:56 -0800160 }
161 }
162
Craig Mautnerdf88d732014-01-27 09:21:32 -0800163 public void startActivity(IntentSender intentSender) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700164 if (mActivityContainer == null) {
165 throw new IllegalStateException("Attempt to call startActivity after release");
166 }
Craig Mautner12ff7392014-02-21 21:08:00 -0800167 if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
168 (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800169 final IIntentSender iIntentSender = intentSender.getTarget();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800170 if (mSurface != null) {
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800171 startActivityIntentSender(iIntentSender);
172 } else {
173 mQueuedPendingIntent = iIntentSender;
174 mQueuedIntent = null;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800175 }
176 }
177
178 public void startActivity(PendingIntent pendingIntent) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700179 if (mActivityContainer == null) {
180 throw new IllegalStateException("Attempt to call startActivity after release");
181 }
Craig Mautner12ff7392014-02-21 21:08:00 -0800182 if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
183 + (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800184 final IIntentSender iIntentSender = pendingIntent.getTarget();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800185 if (mSurface != null) {
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800186 startActivityIntentSender(iIntentSender);
187 } else {
188 mQueuedPendingIntent = iIntentSender;
189 mQueuedIntent = null;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800190 }
191 }
192
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700193 public void release() {
194 if (DEBUG) Log.v(TAG, "release()");
195 if (mActivityContainer == null) {
196 Log.e(TAG, "Duplicate call to release");
197 return;
198 }
199 try {
200 mActivityContainer.release();
201 } catch (RemoteException e) {
202 }
203 mActivityContainer = null;
204
205 if (mSurface != null) {
206 mSurface.release();
207 mSurface = null;
208 }
209
210 mTextureView.setSurfaceTextureListener(null);
211
212 mGuard.close();
213 }
214
215 @Override
216 protected void finalize() throws Throwable {
217 try {
218 if (mGuard != null) {
219 mGuard.warnIfOpen();
220 release();
221 }
222 } finally {
223 super.finalize();
224 }
225 }
226
Craig Mautnerdf88d732014-01-27 09:21:32 -0800227 private void attachToSurfaceWhenReady() {
228 final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700229 if (surfaceTexture == null || mSurface != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800230 // Either not ready to attach, or already attached.
231 return;
232 }
233
Craig Mautner34b73df2014-01-12 21:11:08 -0800234 mSurface = new Surface(surfaceTexture);
Craig Mautner4504de52013-12-20 09:06:56 -0800235 try {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700236 mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi);
Craig Mautner4504de52013-12-20 09:06:56 -0800237 } catch (RemoteException e) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800238 mSurface.release();
239 mSurface = null;
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700240 throw new RuntimeException(
Craig Mautner4504de52013-12-20 09:06:56 -0800241 "ActivityView: Unable to create ActivityContainer. " + e);
242 }
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800243
Craig Mautner12ff7392014-02-21 21:08:00 -0800244 if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
245 mQueuedPendingIntent != null ? "" : "no") + " queued intent");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800246 if (mQueuedIntent != null) {
247 startActivity(mQueuedIntent);
248 mQueuedIntent = null;
249 } else if (mQueuedPendingIntent != null) {
250 startActivityIntentSender(mQueuedPendingIntent);
251 mQueuedPendingIntent = null;
252 }
Craig Mautner4504de52013-12-20 09:06:56 -0800253 }
254
255 private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
256 @Override
257 public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
258 int height) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700259 if (mActivityContainer == null) {
260 return;
261 }
Craig Mautner12ff7392014-02-21 21:08:00 -0800262 if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height="
263 + height);
Craig Mautner4504de52013-12-20 09:06:56 -0800264 mWidth = width;
265 mHeight = height;
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700266 attachToSurfaceWhenReady();
Craig Mautner4504de52013-12-20 09:06:56 -0800267 }
268
269 @Override
270 public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
271 int height) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700272 if (mActivityContainer == null) {
273 return;
274 }
Craig Mautner12ff7392014-02-21 21:08:00 -0800275 if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
Craig Mautner4504de52013-12-20 09:06:56 -0800276 }
277
278 @Override
279 public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700280 if (mActivityContainer == null) {
281 return true;
282 }
Craig Mautner12ff7392014-02-21 21:08:00 -0800283 if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed");
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700284 mSurface.release();
285 mSurface = null;
286 try {
287 mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi);
288 } catch (RemoteException e) {
289 throw new RuntimeException(
290 "ActivityView: Unable to set surface of ActivityContainer. " + e);
291 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800292 return true;
Craig Mautner4504de52013-12-20 09:06:56 -0800293 }
294
295 @Override
296 public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800297// Log.d(TAG, "onSurfaceTextureUpdated");
Craig Mautner4504de52013-12-20 09:06:56 -0800298 }
299
300 }
Craig Mautnere3a00d72014-04-16 08:31:19 -0700301
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700302 private static class ActivityContainerCallback extends IActivityContainerCallback.Stub {
303 private final WeakReference<ActivityView> mActivityViewWeakReference;
304
305 ActivityContainerCallback(ActivityView activityView) {
306 mActivityViewWeakReference = new WeakReference<ActivityView>(activityView);
307 }
308
Craig Mautnere3a00d72014-04-16 08:31:19 -0700309 @Override
310 public void setVisible(IBinder container, boolean visible) {
Craig Mautnerf4c909b2014-04-17 18:39:38 -0700311 if (DEBUG) Log.v(TAG, "setVisible(): container=" + container + " visible=" + visible +
312 " ActivityView=" + mActivityViewWeakReference.get());
Craig Mautnere3a00d72014-04-16 08:31:19 -0700313 }
314 }
Craig Mautner4504de52013-12-20 09:06:56 -0800315}