1 /*
2  * Copyright (C) 2018 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.infra;
18 
19 import android.annotation.NonNull;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.os.Handler;
23 import android.os.IInterface;
24 import android.util.Slog;
25 
26 import java.io.PrintWriter;
27 import java.util.ArrayList;
28 
29 /**
30  * Base class representing a remote service that can queue multiple pending requests while not
31  * bound.
32  *
33  * @param <S> the concrete remote service class
34  * @param <I> the interface of the binder service
35  */
36 public abstract class AbstractMultiplePendingRequestsRemoteService<S
37         extends AbstractMultiplePendingRequestsRemoteService<S, I>, I extends IInterface>
38         extends AbstractRemoteService<S, I> {
39 
40     private final int mInitialCapacity;
41 
42     protected ArrayList<BasePendingRequest<S, I>> mPendingRequests;
43 
AbstractMultiplePendingRequestsRemoteService(@onNull Context context, @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId, @NonNull VultureCallback<S> callback, @NonNull Handler handler, int bindingFlags, boolean verbose, int initialCapacity)44     public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context,
45             @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
46             @NonNull VultureCallback<S> callback, @NonNull Handler handler,
47             int bindingFlags, boolean verbose, int initialCapacity) {
48         super(context, serviceInterface, componentName, userId, callback, handler, bindingFlags,
49                 verbose);
50         mInitialCapacity = initialCapacity;
51     }
52 
53     @Override // from AbstractRemoteService
handlePendingRequests()54     void handlePendingRequests() {
55         if (mPendingRequests != null) {
56             final int size = mPendingRequests.size();
57             if (mVerbose) Slog.v(mTag, "Sending " + size + " pending requests");
58             for (int i = 0; i < size; i++) {
59                 mPendingRequests.get(i).run();
60             }
61             mPendingRequests = null;
62         }
63     }
64 
65     @Override // from AbstractRemoteService
handleOnDestroy()66     protected void handleOnDestroy() {
67         if (mPendingRequests != null) {
68             final int size = mPendingRequests.size();
69             if (mVerbose) Slog.v(mTag, "Canceling " + size + " pending requests");
70             for (int i = 0; i < size; i++) {
71                 mPendingRequests.get(i).cancel();
72             }
73             mPendingRequests = null;
74         }
75     }
76 
77     @Override // from AbstractRemoteService
handleBindFailure()78     final void handleBindFailure() {
79         if (mPendingRequests != null) {
80             final int size = mPendingRequests.size();
81             if (mVerbose) Slog.v(mTag, "Sending failure to " + size + " pending requests");
82             for (int i = 0; i < size; i++) {
83                 final BasePendingRequest<S, I> request = mPendingRequests.get(i);
84                 request.onFailed();
85                 request.finish();
86             }
87             mPendingRequests = null;
88         }
89     }
90 
91     @Override // from AbstractRemoteService
dump(@onNull String prefix, @NonNull PrintWriter pw)92     public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
93         super.dump(prefix, pw);
94 
95         pw.append(prefix).append("initialCapacity=").append(String.valueOf(mInitialCapacity))
96                 .println();
97         final int size = mPendingRequests == null ? 0 : mPendingRequests.size();
98         pw.append(prefix).append("pendingRequests=").append(String.valueOf(size)).println();
99     }
100 
101     @Override // from AbstractRemoteService
handlePendingRequestWhileUnBound(@onNull BasePendingRequest<S, I> pendingRequest)102     void handlePendingRequestWhileUnBound(@NonNull BasePendingRequest<S, I> pendingRequest) {
103         if (mPendingRequests == null) {
104             mPendingRequests = new ArrayList<>(mInitialCapacity);
105         }
106         mPendingRequests.add(pendingRequest);
107         if (mVerbose) {
108             Slog.v(mTag, "queued " + mPendingRequests.size() + " requests; last=" + pendingRequest);
109         }
110     }
111 }
112