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 android.os;
18 
19 import android.app.Service;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.ServiceConnection;
24 
25 import java.util.concurrent.BlockingQueue;
26 import java.util.concurrent.LinkedBlockingQueue;
27 import java.util.concurrent.TimeUnit;
28 
29 /**
30 * Service used by {@link BinderWorkSourceTest}.
31 */
32 public class BinderWorkSourceNestedService extends Service {
33     private final IBinderWorkSourceNestedService.Stub mBinder =
34             new IBinderWorkSourceNestedService.Stub() {
35 
36         public int[] nestedCallWithWorkSourceToSet(int uidToBlame) {
37             final int uid =  Binder.getCallingWorkSourceUid();
38             if (uidToBlame != ThreadLocalWorkSource.UID_NONE) {
39                 Binder.setCallingWorkSourceUid(uidToBlame);
40             }
41             final int nestedUid = callGetIncomingWorkSourceUid();
42             return new int[] {uid, nestedUid};
43         }
44 
45         public int[] nestedCall() {
46             final int uid =  Binder.getCallingWorkSourceUid();
47             final int nestedUid = callGetIncomingWorkSourceUid();
48             return new int[] {uid, nestedUid};
49         }
50 
51         private int callGetIncomingWorkSourceUid() {
52             BlockingQueue<IBinderWorkSourceService> blockingQueue =
53                     new LinkedBlockingQueue<>();
54             ServiceConnection mConnection = new ServiceConnection() {
55                 public void onServiceConnected(ComponentName name, IBinder service) {
56                     blockingQueue.add(IBinderWorkSourceService.Stub.asInterface(service));
57                 }
58 
59                 public void onServiceDisconnected(ComponentName name) {
60                 }
61             };
62 
63             Context context = getApplicationContext();
64             context.bindService(
65                     new Intent(context, BinderWorkSourceService.class),
66                     mConnection, Context.BIND_AUTO_CREATE);
67 
68             final IBinderWorkSourceService service;
69             try {
70                 service = blockingQueue.poll(30, TimeUnit.SECONDS);
71             } catch (InterruptedException e) {
72                 throw new RuntimeException(e);
73             }
74             if (service == null) {
75                 throw new RuntimeException("Gave up waiting for BinderWorkSourceService");
76             }
77 
78             try {
79                 return service.getIncomingWorkSourceUid();
80             } catch (RemoteException e) {
81                 throw new RuntimeException(e);
82             } finally {
83                 context.unbindService(mConnection);
84             }
85         }
86     };
87 
onBind(Intent intent)88     public IBinder onBind(Intent intent) {
89         return mBinder;
90     }
91 }
92