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 public static final int GET_ON_CREATE_CALLED_COUNT = 15; 57 58 public static Context sServiceContext = null; 59 60 private static final AtomicReference<String> sLastAttributionTag = new AtomicReference<>(); 61 private static volatile int sOnCreateCount = 0; 62 63 private IBinder mReportObject; 64 private int mStartCount = 1; 65 private int mValue = 0; 66 private int mStartId = -1; 67 private boolean mIsStoppedSelfSuccess; 68 69 private final IBinder mBinder = new Binder() { 70 @Override 71 protected boolean onTransact(int code, Parcel data, Parcel reply, 72 int flags) throws RemoteException { 73 switch (code) { 74 case SET_REPORTER_CODE: 75 data.enforceInterface(SERVICE_LOCAL); 76 mReportObject = data.readStrongBinder(); 77 return true; 78 case GET_VALUE_CODE: 79 data.enforceInterface(SERVICE_LOCAL); 80 reply.writeInt(mValue); 81 return true; 82 case SET_VALUE_CODE: 83 data.enforceInterface(SERVICE_LOCAL); 84 mValue = data.readInt(); 85 return true; 86 case GET_PID_CODE: 87 data.enforceInterface(SERVICE_LOCAL); 88 reply.writeInt(Process.myPid()); 89 return true; 90 case GET_UID_CODE: 91 data.enforceInterface(SERVICE_LOCAL); 92 reply.writeInt(Process.myUid()); 93 return true; 94 case GET_PPID_CODE: 95 data.enforceInterface(SERVICE_LOCAL); 96 reply.writeInt(Process.myPpid()); 97 return true; 98 case GET_ZYGOTE_PRELOAD_CALLED: 99 data.enforceInterface(SERVICE_LOCAL); 100 reply.writeBoolean(ZygotePreload.preloadCalled()); 101 return true; 102 case STOP_SELF_RESULT_CODE: 103 synchronized (LocalService.this) { 104 mIsStoppedSelfSuccess = stopSelfResult(mStartId); 105 } 106 return true; 107 case STOP_SELF_CODE: 108 stopSelf(mStartId); 109 return true; 110 case GET_ON_CREATE_CALLED_COUNT: 111 data.enforceInterface(SERVICE_LOCAL); 112 reply.writeInt(sOnCreateCount); 113 return true; 114 default: 115 return super.onTransact(code, data, reply, flags); 116 } 117 } 118 }; 119 LocalService()120 public LocalService() { 121 } 122 123 @Override onCreate()124 public void onCreate() { 125 super.onCreate(); 126 sLastAttributionTag.set(getAttributionTag()); 127 sOnCreateCount++; 128 } 129 getAndClearLastAttributionTag()130 public static String getAndClearLastAttributionTag() { 131 return sLastAttributionTag.getAndSet(null); 132 } 133 134 @Override onStart(Intent intent, int startId)135 public void onStart(Intent intent, int startId) { 136 mStartId = startId; 137 if (intent.getExtras() != null) { 138 IBinderParcelable parcelable 139 = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME); 140 mReportObject = parcelable.binder; 141 if (mReportObject != null) { 142 bindAction(STARTED_CODE); 143 } 144 } 145 if (sServiceContext == null) { 146 sServiceContext = this; 147 } 148 } 149 150 @Override onDestroy()151 public void onDestroy() { 152 if (mReportObject != null) { 153 bindAction(DESTROYED_CODE); 154 } 155 } 156 157 @Override onBind(Intent intent)158 public IBinder onBind(Intent intent) { 159 if (sServiceContext == null) { 160 sServiceContext = this; 161 } 162 return mBinder; 163 } 164 165 @Override onUnbind(Intent intent)166 public boolean onUnbind(Intent intent) { 167 if (mReportObject != null) { 168 synchronized (this) { 169 if (mIsStoppedSelfSuccess) { 170 bindAction(STOP_SELF_SUCCESS_UNBIND_CODE); 171 } else { 172 bindAction(UNBIND_CODE); 173 } 174 } 175 } 176 return true; 177 } 178 179 @Override onRebind(Intent intent)180 public void onRebind(Intent intent) { 181 if (mReportObject != null) { 182 bindAction(REBIND_CODE); 183 } 184 } 185 bindAction(final int bindCode)186 private void bindAction(final int bindCode) { 187 try { 188 Parcel data = Parcel.obtain(); 189 data.writeInterfaceToken(SERVICE_LOCAL); 190 if (bindCode == STARTED_CODE) { 191 data.writeInt(mStartCount); 192 mStartCount++; 193 } 194 mReportObject.transact( 195 bindCode, data, null, 0); 196 data.recycle(); 197 } catch (RemoteException e) { 198 // fail 199 } 200 } 201 } 202