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