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