18662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate/* 28662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * Copyright (C) 2012 The Android Open Source Project 38662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * 48662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * Licensed under the Apache License, Version 2.0 (the "License"); 58662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * you may not use this file except in compliance with the License. 68662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * You may obtain a copy of the License at 78662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * 88662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * http://www.apache.org/licenses/LICENSE-2.0 98662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * 108662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * Unless required by applicable law or agreed to in writing, software 118662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * distributed under the License is distributed on an "AS IS" BASIS, 128662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * See the License for the specific language governing permissions and 148662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate * limitations under the License. 158662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate */ 168662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 178662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tatepackage com.android.server; 188662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 198662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.content.Context; 208662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.content.Intent; 218662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.content.pm.PackageManager; 228662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.Binder; 238662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.Handler; 248662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.IBinder; 258662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.IUpdateLock; 268662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.RemoteException; 278662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.TokenWatcher; 288662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.os.UpdateLock; 295ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 308662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport android.util.Slog; 318662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 32fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils; 33fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey 348662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport java.io.FileDescriptor; 358662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tateimport java.io.PrintWriter; 368662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 378662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tatepublic class UpdateLockService extends IUpdateLock.Stub { 388662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate static final boolean DEBUG = false; 398662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate static final String TAG = "UpdateLockService"; 408662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 418662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate // signatureOrSystem required to use update locks 428662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate static final String PERMISSION = "android.permission.UPDATE_LOCK"; 438662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 448662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Context mContext; 458662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate LockWatcher mLocks; 468662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 478662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate class LockWatcher extends TokenWatcher { 488662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate LockWatcher(Handler h, String tag) { 498662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate super(h, tag); 508662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 518662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 528662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate public void acquired() { 538662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate if (DEBUG) { 548662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Slog.d(TAG, "first acquire; broadcasting convenient=false"); 558662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 568662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate sendLockChangedBroadcast(false); 578662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 588662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate public void released() { 598662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate if (DEBUG) { 608662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Slog.d(TAG, "last release; broadcasting convenient=true"); 618662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 628662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate sendLockChangedBroadcast(true); 638662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 648662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 658662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 668662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate UpdateLockService(Context context) { 678662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mContext = context; 688662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mLocks = new LockWatcher(new Handler(), "UpdateLocks"); 698662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 708662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate // Consider just-booting to be a reasonable time to allow 718662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate // interruptions for update installation etc. 728662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate sendLockChangedBroadcast(true); 738662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 748662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 758662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate void sendLockChangedBroadcast(boolean state) { 768662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate // Safe early during boot because this broadcast only goes to registered receivers. 778662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate long oldIdent = Binder.clearCallingIdentity(); 788662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate try { 798662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Intent intent = new Intent(UpdateLock.UPDATE_LOCK_CHANGED) 808662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate .putExtra(UpdateLock.NOW_IS_CONVENIENT, state) 818662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate .putExtra(UpdateLock.TIMESTAMP, System.currentTimeMillis()) 825bb59daf42fb24c1131effd4265c2386304fecebChristopher Tate .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 835ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 848662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } finally { 858662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Binder.restoreCallingIdentity(oldIdent); 868662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 878662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 888662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 898662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate @Override 908662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate public void acquireUpdateLock(IBinder token, String tag) throws RemoteException { 918662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate if (DEBUG) { 928662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Slog.d(TAG, "acquire(" + token + ") by " + makeTag(tag)); 938662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 948662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 958662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mContext.enforceCallingOrSelfPermission(PERMISSION, "acquireUpdateLock"); 968662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mLocks.acquire(token, makeTag(tag)); 978662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 988662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 998662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate @Override 1008662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate public void releaseUpdateLock(IBinder token) throws RemoteException { 1018662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate if (DEBUG) { 1028662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate Slog.d(TAG, "release(" + token + ')'); 1038662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 1048662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 1058662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mContext.enforceCallingOrSelfPermission(PERMISSION, "releaseUpdateLock"); 1068662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mLocks.release(token); 1078662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate }; 1088662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 1098662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate private String makeTag(String tag) { 1108662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate return "{tag=" + tag 1118662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate + " uid=" + Binder.getCallingUid() 1128662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate + " pid=" + Binder.getCallingPid() + '}'; 1138662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 1148662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate 1158662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate @Override 1168662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 117fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1188662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate mLocks.dump(pw); 1198662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate } 1208662cab5c6a01ea5c426512e6f6d2cf3e158aea0Christopher Tate} 121