1b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik/** 2b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Copyright (C) 2007 The Android Open Source Project 3b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * 4b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * use this file except in compliance with the License. You may obtain a copy 6b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * of the License at 7b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * 8b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * http://www.apache.org/licenses/LICENSE-2.0 9b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * 10b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Unless required by applicable law or agreed to in writing, software 11b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * License for the specific language governing permissions and limitations 14b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * under the License. 15b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 16b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 17b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikpackage com.google.android.googlelogin; 18b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 19b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport com.google.android.googleapps.IGoogleLoginService; 20b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 21b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport android.content.ComponentName; 22b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport android.content.Context; 23b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport android.content.ServiceConnection; 24b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport android.os.RemoteException; 25b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport android.os.IBinder; 26b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport android.os.Looper; 27b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 28b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport java.util.concurrent.locks.Condition; 29b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport java.util.concurrent.locks.Lock; 30b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikimport java.util.concurrent.locks.ReentrantLock; 31b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 32b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik/** 33b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * A helper designed for use by services and background tasks. 34b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * This class provides blocking calls that wrap the binding to the 35b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * {@link IGoogleLoginService GoogleLoginService} and the various 36b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * calls to it. (Be sure not to call these blocking methods 37b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * from your main thread, though; you always need to create a separate 38b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * worker thread for operations that may block.) 39b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * <p> 40b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * It's best to instantiate this class once 41b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * and make calls on that instance when necessary. 42b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * The helper does not unbind from the GoogleLoginService after 43b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * each call. 44b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * <p> 45b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * When you are done with this object, call close() to unbind from the 46b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * GoogleLoginService. 47b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 48b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erikpublic class GoogleLoginServiceBlockingHelper { 49b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private static final String TAG = "GoogleLoginServiceBlockingHelper"; 50b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 51b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private final Context mContext; 52b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private volatile IGoogleLoginService mGoogleLoginService = null; 53b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private Lock mGoogleLoginServiceLock = new ReentrantLock(); 54b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private Condition mBindWaitCondition = mGoogleLoginServiceLock.newCondition(); 55b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private ServiceConnection mServiceConnection; 56b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 57b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private final int mMinDelaySecs; 58b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private final int mMaxDelaySecs; 59b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private final double mBackoffFactor; 60b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private int mDelay; 61b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 62b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 63b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Whether the Google login service we've bound to is the 64b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Google-provided service. This will be set after we get a callback on the 65b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * service connection, so the value is only valid if 66b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * {@link #mGoogleLoginService} is not null. 67b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * <p> 68b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Locked with the {@link #mGoogleLoginServiceLock} also. 69b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 70b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private boolean mGlsVerified; 71b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 72b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 73b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Initializes the helper. 74b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @param context the Context in which this helper is running 75b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @throws GoogleLoginServiceNotFoundException if the Google login service cannot be found. 76b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 77b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik public GoogleLoginServiceBlockingHelper(Context context) 78b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik throws GoogleLoginServiceNotFoundException { 79b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mMinDelaySecs = 5; 80b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mMaxDelaySecs = 5 * 60; // 5 minutes 81b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mBackoffFactor = 2.0; 82b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mDelay = mMinDelaySecs; 83b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mContext = context; 84b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 85b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik // Ensure the Google Login Service is available 86b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik if (!GoogleAppsVerifier.isServiceAvailable(context, 87b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik GoogleLoginServiceConstants.FULLY_QUALIFIED_SERVICE_NAME)) { 88b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik throw new GoogleLoginServiceNotFoundException( 89b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik GoogleLoginServiceConstants.ERROR_CODE_GLS_NOT_FOUND); 90b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 91b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 92b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.lock(); 93b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 94b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mServiceConnection = new ServiceConnection() { 95b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik public void onServiceConnected(ComponentName className, IBinder service) { 96b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 97b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.lock(); 98b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 99b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /* 100b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Verify that the service we just connected to is 101b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * provided by Google. Eventually, this will manifest 102b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * into an exception, but we can't throw it here because 103b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * our client isn't in the call stack right now. 104b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 105b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGlsVerified = GoogleAppsVerifier.isGoogleAppsVerified(mContext); 106b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 107b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginService = IGoogleLoginService.Stub.asInterface(service); 108b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 109b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mBindWaitCondition.signalAll(); 110b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } finally { 111b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.unlock(); 112b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 113b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 114b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 115b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik public void onServiceDisconnected(ComponentName className) { 116b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.lock(); 117b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginService = null; 118b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.unlock(); 119b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 120b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik }; 121b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 122b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik if (!mContext.bindService(GoogleLoginServiceConstants.SERVICE_INTENT, 123b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mServiceConnection, Context.BIND_AUTO_CREATE)) { 124b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik throw new GoogleLoginServiceNotFoundException( 125b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik GoogleLoginServiceConstants.ERROR_CODE_GLS_NOT_FOUND); 126b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 127b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } finally { 128b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.unlock(); 129b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 130b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 131b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 132b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 133b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Releases the binding to the GoogleLoginService (if one exists). This object 134b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * is no longer usable one this method is invoked. 135b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 136b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik public void close() { 137b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.lock(); 138b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 139b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik if (mServiceConnection != null) { 140b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mContext.unbindService(mServiceConnection); 141b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mServiceConnection = null; 142b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginService = null; 143b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 144b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } finally { 145b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.unlock(); 146b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 147b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 148b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 149b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 150b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Sleep for an exponentially-increasing length of time (bounded 151b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * by mMinDelaySecs and mMaxDelaySecs). 152b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 153b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private void delay() { 154b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 155b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik Thread.sleep(mDelay * 1000L); 156b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } catch (InterruptedException ignore) { 157b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik // just delay for less time 158b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 159b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mDelay *= mBackoffFactor; 160b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik if (mDelay > mMaxDelaySecs) mDelay = mMaxDelaySecs; 161b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 162b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 163b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 164b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Reset the sleep time used by delay() to the minimum. 165b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 166b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private void resetDelay() { 167b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mDelay = mMinDelaySecs; 168b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 169b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 170b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 171b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Waits for mGoogleLoginService to be nun-null and then returns it. It is set in the 172b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * onServiceConnected that is called as a result of the bind that is called by the 173b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * constructor. 174b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @return the GoogleLoginService, guaranteed to be non-null 175b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @throws GoogleLoginServiceNotFoundException if the Google login service cannot be found. 176b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 177b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private IGoogleLoginService getLoginService() throws GoogleLoginServiceNotFoundException { 178b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik if (Looper.myLooper() == mContext.getMainLooper()) { 179b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik throw new IllegalStateException("calling GoogleLoginServiceBlockingHelper methods " 180b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik + "from your main thread can lead to deadlock"); 181b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 182b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 183b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.lock(); 184b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik while (mGoogleLoginService == null) { 185b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 186b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mBindWaitCondition.await(); 187b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } catch (InterruptedException e) { 188b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik // keep waiting 189b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 190b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 191b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 192b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik checkGoogleLoginServiceVerificationLocked(); 193b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 194b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik return mGoogleLoginService; 195b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } finally { 196b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik mGoogleLoginServiceLock.unlock(); 197b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 198b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 199b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 200b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik private void checkGoogleLoginServiceVerificationLocked() 201b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik throws GoogleLoginServiceNotFoundException { 202b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik if (mGoogleLoginService != null && !mGlsVerified) { 203b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik throw new GoogleLoginServiceNotFoundException( 204b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik GoogleLoginServiceConstants.ERROR_CODE_GLS_VERIFICATION_FAILED); 205b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 206b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 207b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 208b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 209b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Gets the login service via getLoginService, which may block, and then 210b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * invokes getAndroidId on it. 211b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * 212b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @see IGoogleLoginService#getAndroidId() 213b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @return the Android ID for this device (a 64-bit value unique to this 214b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * device); 0 if the device is not registered with google or if the Android 215b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * ID is otherwise unavailable. 216b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @throws GoogleLoginServiceNotFoundException if the Google login service cannot be found. 217b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 218b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik public static long getAndroidId(Context context) throws GoogleLoginServiceNotFoundException { 219b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik GoogleLoginServiceBlockingHelper h = new GoogleLoginServiceBlockingHelper(context); 220b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 221b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik return h.getAndroidId(); 222b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } finally { 223b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik h.close(); 224b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 225b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 226b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik 227b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik /** 228b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * Gets the login service via getLoginService, which may block, and then 229b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * invokes getAndroidId on it. 230b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * 231b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @see IGoogleLoginService#getAndroidId() 232b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @return the Android ID for this device (a 64-bit value unique to this 233b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * device); 0 if the device is not registered with google or if the Android 234b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * ID is otherwise unavailable. 235b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik * @throws GoogleLoginServiceNotFoundException if the Google login service cannot be found. 236b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik */ 237b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik public long getAndroidId() throws GoogleLoginServiceNotFoundException { 238b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik resetDelay(); 239b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik while (true) { 240b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik IGoogleLoginService loginService = getLoginService(); 241b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik try { 242b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik return loginService.getAndroidId(); 243b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } catch (RemoteException e) { 244b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik // the next call to getLoginService will wait until the service 245b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik // is reconnected 246b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik delay(); 247b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 248b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 249b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik } 250b0143ecb5bfc6eeb272b2ec790b40d252c32e6a1Erik} 251