blob: 113f1230386eac10a385cf5d486e2359559459ff [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;
Craig Mautnerdf88d732014-01-27 09:21:32 -080036import android.view.View;
Craig Mautner4504de52013-12-20 09:06:56 -080037import android.view.ViewGroup;
38import android.view.WindowManager;
39
Craig Mautner95da1082014-02-24 17:54:35 -080040/** @hide */
Craig Mautner4504de52013-12-20 09:06:56 -080041public class ActivityView extends ViewGroup {
Craig Mautner34b73df2014-01-12 21:11:08 -080042 private final String TAG = "ActivityView";
Craig Mautner12ff7392014-02-21 21:08:00 -080043 private final boolean DEBUG = false;
Craig Mautner34b73df2014-01-12 21:11:08 -080044
Craig Mautner4504de52013-12-20 09:06:56 -080045 private final TextureView mTextureView;
46 private IActivityContainer mActivityContainer;
47 private Activity mActivity;
Craig Mautner4504de52013-12-20 09:06:56 -080048 private int mWidth;
49 private int mHeight;
Craig Mautner34b73df2014-01-12 21:11:08 -080050 private Surface mSurface;
Craig Mautner4504de52013-12-20 09:06:56 -080051
Craig Mautner4e5b67e2014-02-07 15:30:03 -080052 // Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
53 IIntentSender mQueuedPendingIntent;
54 Intent mQueuedIntent;
55
Craig Mautner4504de52013-12-20 09:06:56 -080056 public ActivityView(Context context) {
57 this(context, null);
58 }
59
60 public ActivityView(Context context, AttributeSet attrs) {
61 this(context, attrs, 0);
62 }
63
64 public ActivityView(Context context, AttributeSet attrs, int defStyle) {
65 super(context, attrs, defStyle);
66
67 while (context instanceof ContextWrapper) {
68 if (context instanceof Activity) {
69 mActivity = (Activity)context;
70 break;
71 }
72 context = ((ContextWrapper)context).getBaseContext();
73 }
74 if (mActivity == null) {
75 throw new IllegalStateException("The ActivityView's Context is not an Activity.");
76 }
77
78 mTextureView = new TextureView(context);
79 mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
80 addView(mTextureView);
Craig Mautner12ff7392014-02-21 21:08:00 -080081 if (DEBUG) Log.v(TAG, "ctor()");
Craig Mautner4504de52013-12-20 09:06:56 -080082 }
83
84 @Override
85 protected void onLayout(boolean changed, int l, int t, int r, int b) {
Griff Hazenaf745f62014-02-10 08:58:32 -080086 mTextureView.layout(0, 0, r - l, b - t);
Craig Mautner4504de52013-12-20 09:06:56 -080087 }
88
89 @Override
90 protected void onAttachedToWindow() {
Craig Mautner12ff7392014-02-21 21:08:00 -080091 if (DEBUG) Log.v(TAG, "onAttachedToWindow()");
92 super.onAttachedToWindow();
Craig Mautner4504de52013-12-20 09:06:56 -080093 try {
94 final IBinder token = mActivity.getActivityToken();
95 mActivityContainer =
96 ActivityManagerNative.getDefault().createActivityContainer(token, null);
97 } catch (RemoteException e) {
98 throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. "
99 + e);
100 }
101
Craig Mautnerdf88d732014-01-27 09:21:32 -0800102 attachToSurfaceWhenReady();
Craig Mautner4504de52013-12-20 09:06:56 -0800103 }
104
105 @Override
106 protected void onDetachedFromWindow() {
Craig Mautner12ff7392014-02-21 21:08:00 -0800107 if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer);
108 super.onDetachedFromWindow();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800109 if (mActivityContainer != null) {
110 detach();
Craig Mautner95da1082014-02-24 17:54:35 -0800111 try {
112 ActivityManagerNative.getDefault().deleteActivityContainer(mActivityContainer);
113 } catch (RemoteException e) {
114 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800115 mActivityContainer = null;
116 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800117 }
118
119 @Override
Craig Mautnerdf88d732014-01-27 09:21:32 -0800120 protected void onWindowVisibilityChanged(int visibility) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800121 if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800122 super.onWindowVisibilityChanged(visibility);
Craig Mautner12ff7392014-02-21 21:08:00 -0800123 switch (visibility) {
124 case View.VISIBLE:
125 attachToSurfaceWhenReady();
126 break;
127 case View.INVISIBLE:
128 break;
129 case View.GONE:
Craig Mautner12ff7392014-02-21 21:08:00 -0800130 break;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800131 }
132 }
133
Jeff Brown38f96e52014-02-11 14:32:56 -0800134 private boolean injectInputEvent(InputEvent event) {
135 try {
136 return mActivityContainer != null && mActivityContainer.injectEvent(event);
137 } catch (RemoteException e) {
138 return false;
139 }
140 }
141
142 @Override
143 public boolean onTouchEvent(MotionEvent event) {
144 return injectInputEvent(event) || super.onTouchEvent(event);
145 }
146
147 @Override
148 public boolean onGenericMotionEvent(MotionEvent event) {
149 if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
150 if (injectInputEvent(event)) {
151 return true;
152 }
153 }
154 return super.onGenericMotionEvent(event);
155 }
156
Craig Mautnerdf88d732014-01-27 09:21:32 -0800157 public boolean isAttachedToDisplay() {
158 return mSurface != null;
Craig Mautner4504de52013-12-20 09:06:56 -0800159 }
160
161 public void startActivity(Intent intent) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800162 if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
163 (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautnerdf88d732014-01-27 09:21:32 -0800164 if (mSurface != null) {
Craig Mautner4504de52013-12-20 09:06:56 -0800165 try {
166 mActivityContainer.startActivity(intent);
167 } catch (RemoteException e) {
168 throw new IllegalStateException("ActivityView: Unable to startActivity. " + e);
169 }
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800170 } else {
171 mQueuedIntent = intent;
172 mQueuedPendingIntent = null;
173 }
174 }
175
176 private void startActivityIntentSender(IIntentSender iIntentSender) {
177 try {
178 mActivityContainer.startActivityIntentSender(iIntentSender);
179 } catch (RemoteException e) {
180 throw new IllegalStateException(
181 "ActivityView: Unable to startActivity from IntentSender. " + e);
Craig Mautner4504de52013-12-20 09:06:56 -0800182 }
183 }
184
Craig Mautnerdf88d732014-01-27 09:21:32 -0800185 public void startActivity(IntentSender intentSender) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800186 if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
187 (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800188 final IIntentSender iIntentSender = intentSender.getTarget();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800189 if (mSurface != null) {
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800190 startActivityIntentSender(iIntentSender);
191 } else {
192 mQueuedPendingIntent = iIntentSender;
193 mQueuedIntent = null;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800194 }
195 }
196
197 public void startActivity(PendingIntent pendingIntent) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800198 if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
199 + (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800200 final IIntentSender iIntentSender = pendingIntent.getTarget();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800201 if (mSurface != null) {
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800202 startActivityIntentSender(iIntentSender);
203 } else {
204 mQueuedPendingIntent = iIntentSender;
205 mQueuedIntent = null;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800206 }
207 }
208
209 private void attachToSurfaceWhenReady() {
210 final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
211 if (mActivityContainer == null || surfaceTexture == null || mSurface != null) {
212 // Either not ready to attach, or already attached.
213 return;
214 }
215
Craig Mautner4504de52013-12-20 09:06:56 -0800216 WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
217 DisplayMetrics metrics = new DisplayMetrics();
218 wm.getDefaultDisplay().getMetrics(metrics);
219
Craig Mautner34b73df2014-01-12 21:11:08 -0800220 mSurface = new Surface(surfaceTexture);
Craig Mautner4504de52013-12-20 09:06:56 -0800221 try {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800222 mActivityContainer.attachToSurface(mSurface, mWidth, mHeight, metrics.densityDpi);
Craig Mautner4504de52013-12-20 09:06:56 -0800223 } catch (RemoteException e) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800224 mSurface.release();
225 mSurface = null;
Craig Mautner4504de52013-12-20 09:06:56 -0800226 throw new IllegalStateException(
227 "ActivityView: Unable to create ActivityContainer. " + e);
228 }
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800229
Craig Mautner12ff7392014-02-21 21:08:00 -0800230 if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
231 mQueuedPendingIntent != null ? "" : "no") + " queued intent");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800232 if (mQueuedIntent != null) {
233 startActivity(mQueuedIntent);
234 mQueuedIntent = null;
235 } else if (mQueuedPendingIntent != null) {
236 startActivityIntentSender(mQueuedPendingIntent);
237 mQueuedPendingIntent = null;
238 }
Craig Mautner4504de52013-12-20 09:06:56 -0800239 }
240
Craig Mautnerdf88d732014-01-27 09:21:32 -0800241 private void detach() {
Craig Mautner12ff7392014-02-21 21:08:00 -0800242 if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay());
Craig Mautnerdf88d732014-01-27 09:21:32 -0800243 if (mSurface != null) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800244 try {
245 mActivityContainer.detachFromDisplay();
246 } catch (RemoteException e) {
247 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800248 mSurface.release();
249 mSurface = null;
250 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800251 }
252
Craig Mautner4504de52013-12-20 09:06:56 -0800253 private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
254 @Override
255 public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
256 int height) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800257 if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height="
258 + height);
Craig Mautner4504de52013-12-20 09:06:56 -0800259 mWidth = width;
260 mHeight = height;
261 if (mActivityContainer != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800262 attachToSurfaceWhenReady();
Craig Mautner4504de52013-12-20 09:06:56 -0800263 }
264 }
265
266 @Override
267 public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
268 int height) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800269 if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
Craig Mautner4504de52013-12-20 09:06:56 -0800270 }
271
272 @Override
273 public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800274 if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed");
Craig Mautnerdf88d732014-01-27 09:21:32 -0800275 detach();
Craig Mautner34b73df2014-01-12 21:11:08 -0800276 return true;
Craig Mautner4504de52013-12-20 09:06:56 -0800277 }
278
279 @Override
280 public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800281// Log.d(TAG, "onSurfaceTextureUpdated");
Craig Mautner4504de52013-12-20 09:06:56 -0800282 }
283
284 }
285}