1 /*
2  * Copyright (C) 2008 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.app.stubs;
18 
19 import android.app.Service;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.Binder;
23 import android.os.IBinder;
24 import android.os.Parcel;
25 import android.os.Process;
26 import android.os.RemoteException;
27 
28 import com.android.compatibility.common.util.IBinderParcelable;
29 
30 import java.util.concurrent.atomic.AtomicReference;
31 
32 public class LocalService extends Service {
33     public static final String SERVICE_LOCAL =
34             "android.app.cts.activity.SERVICE_LOCAL";
35     public static final String SERVICE_LOCAL_GRANTED =
36             "android.app.cts.activity.SERVICE_LOCAL_GRANTED";
37     public static final String SERVICE_LOCAL_DENIED =
38             "android.app.cts.activity.SERVICE_LOCAL_DENIED";
39 
40     public static final String REPORT_OBJ_NAME = "report";
41 
42     public static final int STARTED_CODE = 1;
43     public static final int DESTROYED_CODE = 2;
44     public static final int SET_REPORTER_CODE = 3;
45     public static final int UNBIND_CODE = 4;
46     public static final int REBIND_CODE = 5;
47     public static final int GET_VALUE_CODE = 6;
48     public static final int SET_VALUE_CODE = 7;
49     public static final int GET_PID_CODE = 8;
50     public static final int GET_UID_CODE = 9;
51     public static final int GET_PPID_CODE = 10;
52     public static final int GET_ZYGOTE_PRELOAD_CALLED = 11;
53     public static final int STOP_SELF_CODE = 12;
54     public static final int STOP_SELF_RESULT_CODE = 13;
55     public static final int STOP_SELF_SUCCESS_UNBIND_CODE = 14;
56 
57     public static Context sServiceContext = null;
58 
59     private static final AtomicReference<String> sLastAttributionTag = new AtomicReference<>();
60 
61     private IBinder mReportObject;
62     private int mStartCount = 1;
63     private int mValue = 0;
64     private int mStartId = -1;
65     private boolean mIsStoppedSelfSuccess;
66 
67     private final IBinder mBinder = new Binder() {
68         @Override
69         protected boolean onTransact(int code, Parcel data, Parcel reply,
70                 int flags) throws RemoteException {
71             switch (code) {
72                 case SET_REPORTER_CODE:
73                     data.enforceInterface(SERVICE_LOCAL);
74                     mReportObject = data.readStrongBinder();
75                     return true;
76                 case GET_VALUE_CODE:
77                     data.enforceInterface(SERVICE_LOCAL);
78                     reply.writeInt(mValue);
79                     return true;
80                 case SET_VALUE_CODE:
81                     data.enforceInterface(SERVICE_LOCAL);
82                     mValue = data.readInt();
83                     return true;
84                 case GET_PID_CODE:
85                     data.enforceInterface(SERVICE_LOCAL);
86                     reply.writeInt(Process.myPid());
87                     return true;
88                 case GET_UID_CODE:
89                     data.enforceInterface(SERVICE_LOCAL);
90                     reply.writeInt(Process.myUid());
91                     return true;
92                 case GET_PPID_CODE:
93                     data.enforceInterface(SERVICE_LOCAL);
94                     reply.writeInt(Process.myPpid());
95                     return true;
96                 case GET_ZYGOTE_PRELOAD_CALLED:
97                     data.enforceInterface(SERVICE_LOCAL);
98                     reply.writeBoolean(ZygotePreload.preloadCalled());
99                     return true;
100                 case STOP_SELF_RESULT_CODE:
101                     synchronized (LocalService.this) {
102                         mIsStoppedSelfSuccess = stopSelfResult(mStartId);
103                     }
104                     return true;
105                 case STOP_SELF_CODE:
106                     stopSelf(mStartId);
107                     return true;
108                 default:
109                     return super.onTransact(code, data, reply, flags);
110             }
111         }
112     };
113 
LocalService()114     public LocalService() {
115     }
116 
117     @Override
onCreate()118     public void onCreate() {
119         super.onCreate();
120         sLastAttributionTag.set(getAttributionTag());
121     }
122 
getAndClearLastAttributionTag()123     public static String getAndClearLastAttributionTag() {
124         return sLastAttributionTag.getAndSet(null);
125     }
126 
127     @Override
onStart(Intent intent, int startId)128     public void onStart(Intent intent, int startId) {
129         mStartId = startId;
130         if (intent.getExtras() != null) {
131             IBinderParcelable parcelable
132                     = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME);
133             mReportObject = parcelable.binder;
134             if (mReportObject != null) {
135                 bindAction(STARTED_CODE);
136             }
137         }
138         if (sServiceContext == null) {
139             sServiceContext = this;
140         }
141     }
142 
143     @Override
onDestroy()144     public void onDestroy() {
145         if (mReportObject != null) {
146             bindAction(DESTROYED_CODE);
147         }
148     }
149 
150     @Override
onBind(Intent intent)151     public IBinder onBind(Intent intent) {
152         if (sServiceContext == null) {
153             sServiceContext = this;
154         }
155         return mBinder;
156     }
157 
158     @Override
onUnbind(Intent intent)159     public boolean onUnbind(Intent intent) {
160         if (mReportObject != null) {
161             synchronized (this) {
162                 if (mIsStoppedSelfSuccess) {
163                     bindAction(STOP_SELF_SUCCESS_UNBIND_CODE);
164                 } else {
165                     bindAction(UNBIND_CODE);
166                 }
167             }
168         }
169         return true;
170     }
171 
172     @Override
onRebind(Intent intent)173     public void onRebind(Intent intent) {
174         if (mReportObject != null) {
175             bindAction(REBIND_CODE);
176         }
177     }
178 
bindAction(final int bindCode)179     private void bindAction(final int bindCode) {
180         try {
181             Parcel data = Parcel.obtain();
182             data.writeInterfaceToken(SERVICE_LOCAL);
183             if (bindCode == STARTED_CODE) {
184                 data.writeInt(mStartCount);
185                 mStartCount++;
186             }
187             mReportObject.transact(
188                     bindCode, data, null, 0);
189             data.recycle();
190         } catch (RemoteException e) {
191             // fail
192         }
193     }
194 }
195