1 /*
2  * Copyright (C) 2020 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 
17 package com.android.systemui.bubbles;
18 
19 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
20 import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.ActivityOptions;
25 import android.app.PendingIntent;
26 import android.window.TaskEmbedder;
27 import android.window.TaskOrganizerTaskEmbedder;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.ShortcutInfo;
31 import android.graphics.Matrix;
32 import android.graphics.Point;
33 import android.graphics.Rect;
34 import android.graphics.Region;
35 import android.view.IWindow;
36 import android.view.SurfaceControl;
37 import android.view.SurfaceHolder;
38 import android.view.SurfaceView;
39 
40 import dalvik.system.CloseGuard;
41 
42 
43 public class BubbleTaskView extends SurfaceView implements SurfaceHolder.Callback,
44         TaskEmbedder.Host {
45     private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleTaskView" : TAG_BUBBLES;
46 
47     private final CloseGuard mGuard = CloseGuard.get();
48     private boolean mOpened; // Protected by mGuard.
49 
50     private TaskEmbedder mTaskEmbedder;
51     private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
52     private final Rect mTmpRect = new Rect();
53 
BubbleTaskView(Context context)54     public BubbleTaskView(Context context) {
55         super(context);
56 
57         mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this);
58         setUseAlpha();
59         getHolder().addCallback(this);
60 
61         mOpened = true;
62         mGuard.open("release");
63     }
64 
setCallback(TaskEmbedder.Listener callback)65     public void setCallback(TaskEmbedder.Listener callback) {
66         if (callback == null) {
67             mTaskEmbedder.setListener(null);
68             return;
69         }
70         mTaskEmbedder.setListener(callback);
71     }
72 
startShortcutActivity(@onNull ShortcutInfo shortcut, @NonNull ActivityOptions options, @Nullable Rect sourceBounds)73     public void startShortcutActivity(@NonNull ShortcutInfo shortcut,
74             @NonNull ActivityOptions options, @Nullable Rect sourceBounds) {
75         mTaskEmbedder.startShortcutActivity(shortcut, options, sourceBounds);
76     }
77 
startActivity(@onNull PendingIntent pendingIntent, @Nullable Intent fillInIntent, @NonNull ActivityOptions options)78     public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
79             @NonNull ActivityOptions options) {
80         mTaskEmbedder.startActivity(pendingIntent, fillInIntent, options);
81     }
82 
onLocationChanged()83     public void onLocationChanged() {
84         mTaskEmbedder.notifyBoundsChanged();
85     }
86 
87     @Override
getScreenBounds()88     public Rect getScreenBounds() {
89         getBoundsOnScreen(mTmpRect);
90         return mTmpRect;
91     }
92 
93     @Override
onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor)94     public void onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor) {
95         setResizeBackgroundColor(bgColor);
96     }
97 
98     @Override
getTapExcludeRegion()99     public Region getTapExcludeRegion() {
100         // Not used
101         return null;
102     }
103 
104     @Override
getScreenToTaskMatrix()105     public Matrix getScreenToTaskMatrix() {
106         // Not used
107         return null;
108     }
109 
110     @Override
getWindow()111     public IWindow getWindow() {
112         // Not used
113         return null;
114     }
115 
116     @Override
getPositionInWindow()117     public Point getPositionInWindow() {
118         // Not used
119         return null;
120     }
121 
122     @Override
canReceivePointerEvents()123     public boolean canReceivePointerEvents() {
124         // Not used
125         return false;
126     }
127 
release()128     public void release() {
129         if (!mTaskEmbedder.isInitialized()) {
130             throw new IllegalStateException(
131                     "Trying to release container that is not initialized.");
132         }
133         performRelease();
134     }
135 
136     @Override
finalize()137     protected void finalize() throws Throwable {
138         try {
139             if (mGuard != null) {
140                 mGuard.warnIfOpen();
141                 performRelease();
142             }
143         } finally {
144             super.finalize();
145         }
146     }
147 
performRelease()148     private void performRelease() {
149         if (!mOpened) {
150             return;
151         }
152         getHolder().removeCallback(this);
153         mTaskEmbedder.release();
154         mTaskEmbedder.setListener(null);
155 
156         mGuard.close();
157         mOpened = false;
158     }
159 
160     @Override
surfaceCreated(SurfaceHolder holder)161     public void surfaceCreated(SurfaceHolder holder) {
162         if (!mTaskEmbedder.isInitialized()) {
163             mTaskEmbedder.initialize(getSurfaceControl());
164         } else {
165             mTmpTransaction.reparent(mTaskEmbedder.getSurfaceControl(),
166                     getSurfaceControl()).apply();
167         }
168         mTaskEmbedder.start();
169     }
170 
171     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)172     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
173         mTaskEmbedder.resizeTask(width, height);
174         mTaskEmbedder.notifyBoundsChanged();
175     }
176 
177     @Override
surfaceDestroyed(SurfaceHolder holder)178     public void surfaceDestroyed(SurfaceHolder holder) {
179         mTaskEmbedder.stop();
180     }
181 }
182