package cn.edu.tsinghua.hpc.tcontacts.service; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import android.content.ContentValues; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Handler; public class TContactSyncHelper { public static boolean tryLock(Context ctx) { Uri uri = Uri.parse("content://tcontact/locked"); Cursor c = ctx.getContentResolver().query(uri, new String[] { "value" }, null, null, null); if (c != null && c.moveToFirst()) { if (Boolean.getBoolean(c.getString((c.getColumnIndex("value"))))) { // The db is locked c.close(); return false; } else { c.close(); ContentValues values = new ContentValues(); values.put("value", "true"); if (ctx.getContentResolver().update(uri, values, null, null) > 0) return true; } } return false; } private static Lock lock = new ReentrantLock(); private static Condition threadCond = lock.newCondition(); public static boolean lock(Context ctx) { // 99% goes here if (tryLock(ctx)) return true; // Unfortunately goes here, then we will wait until the lock is released lock.lock(); LockContentObserver observer = new LockContentObserver(new Handler()); ctx.getContentResolver().registerContentObserver( Uri.parse("content://tcontact/locked"), true, new LockContentObserver(null) { }); try { threadCond.await(); if (tryLock(ctx)) { ctx.getContentResolver().unregisterContentObserver(observer); return true; } } catch (InterruptedException e) { } finally { ctx.getContentResolver().unregisterContentObserver(observer); lock.unlock(); } return false; } private static class LockContentObserver extends ContentObserver { public LockContentObserver(Handler handler) { super(handler); lock.lock(); } @Override public void onChange(boolean selfChange) { threadCond.signal(); lock.unlock(); } @Override public boolean deliverSelfNotifications() { return super.deliverSelfNotifications(); } } public static boolean releaseLock(Context ctx) { Uri uri = Uri.parse("content://tcontact/locked"); ContentValues values = new ContentValues(); values.put("value", "false"); if (ctx.getContentResolver().update(uri, values, null, null) > 0) return true; return false; } }