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.internal.view;
18 
19 import android.annotation.NonNull;
20 import android.graphics.Rect;
21 import android.os.CancellationSignal;
22 import android.view.View;
23 import android.view.ViewGroup;
24 
25 import java.util.function.Consumer;
26 
27 /**
28  * Provides view-specific handling to ScrollCaptureViewSupport.
29  *
30  * @param <V> the View subclass
31  */
32 public interface ScrollCaptureViewHelper<V extends View> {
33     int UP = -1;
34     int DOWN = 1;
35 
36     /**
37      * Contains the result of a scroll request.
38      */
39     class ScrollResult {
40         /**
41          * The area requested in pixels, within {@link #onComputeScrollBounds scroll bounds}, with
42          * top/bottom relative to the scroll position at the start of capture.
43          */
44         public Rect requestedArea;
45         /**
46          * The area, in pixels of the request which is visible and available for capture. In the
47          * same coordinate space as {@link #requestedArea}.
48          */
49         public Rect availableArea;
50         /**
51          * The updated scroll delta (the relative distance, in pixels that the scroll position has
52          * moved from the starting position since capture started).
53          */
54         public int scrollDelta; // visible top offset from start
55 
56         @Override
toString()57         public String toString() {
58             return "ScrollResult{"
59                     + "requestedArea=" + requestedArea
60                     + ", availableArea=" + availableArea
61                     + ", scrollDelta=" + scrollDelta
62                     + '}';
63         }
64     }
65 
66     /**
67      * Verifies that the view is still visible and scrollable. If true is returned here, expect a
68      * call to {@link #onComputeScrollBounds(View)} to follow.
69      *
70      * @param view the view being captured
71      * @return true if the callback should respond to a request with scroll bounds
72      */
onAcceptSession(@onNull V view)73     boolean onAcceptSession(@NonNull V view);
74 
75     /**
76      * Given a scroll capture request for a view, adjust the provided rect to cover the scrollable
77      * content area. The default implementation returns the padded content area of {@code view}.
78      *
79      * @param view the view being captured
80      */
onComputeScrollBounds(@onNull V view)81     @NonNull default Rect onComputeScrollBounds(@NonNull V view) {
82         Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
83         if (view instanceof ViewGroup && ((ViewGroup) view).getClipToPadding()) {
84             bounds.inset(view.getPaddingLeft(), view.getPaddingTop(),
85                     view.getPaddingRight(), view.getPaddingBottom());
86         }
87         return bounds;
88     }
89 
90     /**
91      * Adjust the target for capture.
92      * <p>
93      * Do not touch anything that may change layout positions or sizes on screen. Anything else may
94      * be adjusted as long as it can be reversed in {@link #onPrepareForEnd(View)}.
95      *
96      * @param view         the view being captured
97      * @param scrollBounds the bounds within {@code view} where content scrolls
98      */
onPrepareForStart(@onNull V view, @NonNull Rect scrollBounds)99     void onPrepareForStart(@NonNull V view, @NonNull Rect scrollBounds);
100 
101     /**
102      * Map the request onto the screen.
103      * <p>
104      * Given a rect describing the area to capture, relative to scrollBounds, take actions
105      * necessary to bring the content within the rectangle into the visible area of the view if
106      * needed and return the resulting rectangle describing the position and bounds of the area
107      * which is visible.
108      *  @param view the view being captured
109      * @param scrollBounds the area in which scrolling content moves, local to the {@code containing
110      *                     view}
111      * @param requestRect  the area relative to {@code scrollBounds} which describes the location of
112  *                     content to capture for the request
113      * @param cancellationSignal allows for the request to be cancelled by the caller
114      * @param resultConsumer accepts the result of the request as a {@link ScrollResult}
115      */
116     @NonNull
onScrollRequested(@onNull V view, @NonNull Rect scrollBounds, @NonNull Rect requestRect, CancellationSignal cancellationSignal, Consumer<ScrollResult> resultConsumer)117     void onScrollRequested(@NonNull V view, @NonNull Rect scrollBounds,
118             @NonNull Rect requestRect, CancellationSignal cancellationSignal,
119             Consumer<ScrollResult> resultConsumer);
120 
121     /**
122      * Restore the target after capture.
123      * <p>
124      * Put back anything that was changed in {@link #onPrepareForStart(View, Rect)}.
125      *
126      * @param view the view being captured
127      */
onPrepareForEnd(@onNull V view)128     void onPrepareForEnd(@NonNull V view);
129 }
130