blob: 14f08298e4041c97c13f39461ebf834093e99ac5 [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
40public class ActivityView extends ViewGroup {
Craig Mautner34b73df2014-01-12 21:11:08 -080041 private final String TAG = "ActivityView";
Craig Mautner12ff7392014-02-21 21:08:00 -080042 private final boolean DEBUG = false;
Craig Mautner34b73df2014-01-12 21:11:08 -080043
Craig Mautner4504de52013-12-20 09:06:56 -080044 private final TextureView mTextureView;
45 private IActivityContainer mActivityContainer;
46 private Activity mActivity;
Craig Mautner4504de52013-12-20 09:06:56 -080047 private int mWidth;
48 private int mHeight;
Craig Mautner34b73df2014-01-12 21:11:08 -080049 private Surface mSurface;
Craig Mautner4504de52013-12-20 09:06:56 -080050
Craig Mautner4e5b67e2014-02-07 15:30:03 -080051 // Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
52 IIntentSender mQueuedPendingIntent;
53 Intent mQueuedIntent;
54
Craig Mautner4504de52013-12-20 09:06:56 -080055 public ActivityView(Context context) {
56 this(context, null);
57 }
58
59 public ActivityView(Context context, AttributeSet attrs) {
60 this(context, attrs, 0);
61 }
62
63 public ActivityView(Context context, AttributeSet attrs, int defStyle) {
64 super(context, attrs, defStyle);
65
66 while (context instanceof ContextWrapper) {
67 if (context instanceof Activity) {
68 mActivity = (Activity)context;
69 break;
70 }
71 context = ((ContextWrapper)context).getBaseContext();
72 }
73 if (mActivity == null) {
74 throw new IllegalStateException("The ActivityView's Context is not an Activity.");
75 }
76
77 mTextureView = new TextureView(context);
78 mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
79 addView(mTextureView);
Craig Mautner12ff7392014-02-21 21:08:00 -080080 if (DEBUG) Log.v(TAG, "ctor()");
Craig Mautner4504de52013-12-20 09:06:56 -080081 }
82
83 @Override
84 protected void onLayout(boolean changed, int l, int t, int r, int b) {
Griff Hazenaf745f62014-02-10 08:58:32 -080085 mTextureView.layout(0, 0, r - l, b - t);
Craig Mautner4504de52013-12-20 09:06:56 -080086 }
87
88 @Override
89 protected void onAttachedToWindow() {
Craig Mautner12ff7392014-02-21 21:08:00 -080090 if (DEBUG) Log.v(TAG, "onAttachedToWindow()");
91 super.onAttachedToWindow();
Craig Mautner4504de52013-12-20 09:06:56 -080092 try {
93 final IBinder token = mActivity.getActivityToken();
94 mActivityContainer =
95 ActivityManagerNative.getDefault().createActivityContainer(token, null);
96 } catch (RemoteException e) {
97 throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. "
98 + e);
99 }
100
Craig Mautnerdf88d732014-01-27 09:21:32 -0800101 attachToSurfaceWhenReady();
Craig Mautner4504de52013-12-20 09:06:56 -0800102 }
103
104 @Override
105 protected void onDetachedFromWindow() {
Craig Mautner12ff7392014-02-21 21:08:00 -0800106 if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer);
107 super.onDetachedFromWindow();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800108 if (mActivityContainer != null) {
109 detach();
110 mActivityContainer = null;
111 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800112 }
113
114 @Override
Craig Mautnerdf88d732014-01-27 09:21:32 -0800115 protected void onWindowVisibilityChanged(int visibility) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800116 if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800117 super.onWindowVisibilityChanged(visibility);
Craig Mautner12ff7392014-02-21 21:08:00 -0800118 switch (visibility) {
119 case View.VISIBLE:
120 attachToSurfaceWhenReady();
121 break;
122 case View.INVISIBLE:
123 break;
124 case View.GONE:
125 detach();
126 break;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800127 }
128 }
129
Jeff Brown38f96e52014-02-11 14:32:56 -0800130 private boolean injectInputEvent(InputEvent event) {
131 try {
132 return mActivityContainer != null && mActivityContainer.injectEvent(event);
133 } catch (RemoteException e) {
134 return false;
135 }
136 }
137
138 @Override
139 public boolean onTouchEvent(MotionEvent event) {
140 return injectInputEvent(event) || super.onTouchEvent(event);
141 }
142
143 @Override
144 public boolean onGenericMotionEvent(MotionEvent event) {
145 if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
146 if (injectInputEvent(event)) {
147 return true;
148 }
149 }
150 return super.onGenericMotionEvent(event);
151 }
152
Craig Mautnerdf88d732014-01-27 09:21:32 -0800153 public boolean isAttachedToDisplay() {
154 return mSurface != null;
Craig Mautner4504de52013-12-20 09:06:56 -0800155 }
156
157 public void startActivity(Intent intent) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800158 if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
159 (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautnerdf88d732014-01-27 09:21:32 -0800160 if (mSurface != null) {
Craig Mautner4504de52013-12-20 09:06:56 -0800161 try {
162 mActivityContainer.startActivity(intent);
163 } catch (RemoteException e) {
164 throw new IllegalStateException("ActivityView: Unable to startActivity. " + e);
165 }
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800166 } else {
167 mQueuedIntent = intent;
168 mQueuedPendingIntent = null;
169 }
170 }
171
172 private void startActivityIntentSender(IIntentSender iIntentSender) {
173 try {
174 mActivityContainer.startActivityIntentSender(iIntentSender);
175 } catch (RemoteException e) {
176 throw new IllegalStateException(
177 "ActivityView: Unable to startActivity from IntentSender. " + e);
Craig Mautner4504de52013-12-20 09:06:56 -0800178 }
179 }
180
Craig Mautnerdf88d732014-01-27 09:21:32 -0800181 public void startActivity(IntentSender intentSender) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800182 if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
183 (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800184 final IIntentSender iIntentSender = intentSender.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
193 public void startActivity(PendingIntent pendingIntent) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800194 if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
195 + (isAttachedToDisplay() ? "" : "not") + " attached");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800196 final IIntentSender iIntentSender = pendingIntent.getTarget();
Craig Mautnerdf88d732014-01-27 09:21:32 -0800197 if (mSurface != null) {
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800198 startActivityIntentSender(iIntentSender);
199 } else {
200 mQueuedPendingIntent = iIntentSender;
201 mQueuedIntent = null;
Craig Mautnerdf88d732014-01-27 09:21:32 -0800202 }
203 }
204
205 private void attachToSurfaceWhenReady() {
206 final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
207 if (mActivityContainer == null || surfaceTexture == null || mSurface != null) {
208 // Either not ready to attach, or already attached.
209 return;
210 }
211
Craig Mautner4504de52013-12-20 09:06:56 -0800212 WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
213 DisplayMetrics metrics = new DisplayMetrics();
214 wm.getDefaultDisplay().getMetrics(metrics);
215
Craig Mautner34b73df2014-01-12 21:11:08 -0800216 mSurface = new Surface(surfaceTexture);
Craig Mautner4504de52013-12-20 09:06:56 -0800217 try {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800218 mActivityContainer.attachToSurface(mSurface, mWidth, mHeight, metrics.densityDpi);
Craig Mautner4504de52013-12-20 09:06:56 -0800219 } catch (RemoteException e) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800220 mSurface.release();
221 mSurface = null;
Craig Mautner4504de52013-12-20 09:06:56 -0800222 throw new IllegalStateException(
223 "ActivityView: Unable to create ActivityContainer. " + e);
224 }
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800225
Craig Mautner12ff7392014-02-21 21:08:00 -0800226 if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
227 mQueuedPendingIntent != null ? "" : "no") + " queued intent");
Craig Mautner4e5b67e2014-02-07 15:30:03 -0800228 if (mQueuedIntent != null) {
229 startActivity(mQueuedIntent);
230 mQueuedIntent = null;
231 } else if (mQueuedPendingIntent != null) {
232 startActivityIntentSender(mQueuedPendingIntent);
233 mQueuedPendingIntent = null;
234 }
Craig Mautner4504de52013-12-20 09:06:56 -0800235 }
236
Craig Mautnerdf88d732014-01-27 09:21:32 -0800237 private void detach() {
Craig Mautner12ff7392014-02-21 21:08:00 -0800238 if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay());
Craig Mautnerdf88d732014-01-27 09:21:32 -0800239 if (mSurface != null) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800240 try {
241 mActivityContainer.detachFromDisplay();
242 } catch (RemoteException e) {
243 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800244 mSurface.release();
245 mSurface = null;
246 }
Craig Mautner34b73df2014-01-12 21:11:08 -0800247 }
248
Craig Mautner4504de52013-12-20 09:06:56 -0800249 private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
250 @Override
251 public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
252 int height) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800253 if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height="
254 + height);
Craig Mautner4504de52013-12-20 09:06:56 -0800255 mWidth = width;
256 mHeight = height;
257 if (mActivityContainer != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800258 attachToSurfaceWhenReady();
Craig Mautner4504de52013-12-20 09:06:56 -0800259 }
260 }
261
262 @Override
263 public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
264 int height) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800265 if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
Craig Mautner4504de52013-12-20 09:06:56 -0800266 }
267
268 @Override
269 public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
Craig Mautner12ff7392014-02-21 21:08:00 -0800270 if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed");
Craig Mautnerdf88d732014-01-27 09:21:32 -0800271 detach();
Craig Mautner34b73df2014-01-12 21:11:08 -0800272 return true;
Craig Mautner4504de52013-12-20 09:06:56 -0800273 }
274
275 @Override
276 public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
Craig Mautner34b73df2014-01-12 21:11:08 -0800277// Log.d(TAG, "onSurfaceTextureUpdated");
Craig Mautner4504de52013-12-20 09:06:56 -0800278 }
279
280 }
281}