13a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank/* 23a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank /* 33a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * Copyright (C) 2011 The Android Open Source Project 43a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * 53a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 63a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * you may not use this file except in compliance with the License. 73a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * You may obtain a copy of the License at 83a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * 93a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * http://www.apache.org/licenses/LICENSE-2.0 103a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * 113a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * Unless required by applicable law or agreed to in writing, software 123a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * distributed under the License is distributed on an "AS IS" BASIS, 133a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 143a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * See the License for the specific language governing permissions and 153a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * limitations under the License. 163a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank */ 173a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 183a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankpackage com.android.emailcommon; 193a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 203a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport android.content.Context; 213a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport android.telephony.TelephonyManager; 223a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 23a9f1631fb83200a59e40e23ed366f810d08b6f52Marc Blankimport com.android.emailcommon.utility.Utility; 24560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils; 25a9f1631fb83200a59e40e23ed366f810d08b6f52Marc Blank 263a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport java.io.BufferedReader; 273a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport java.io.BufferedWriter; 283a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport java.io.File; 293a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport java.io.FileReader; 303a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport java.io.FileWriter; 313a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankimport java.io.IOException; 323a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 333a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blankpublic class Device { 343a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank private static String sDeviceId = null; 353a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 363a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank /** 373a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * EAS requires a unique device id, so that sync is possible from a variety of different 383a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * devices (e.g. the syncKey is specific to a device) If we're on an emulator or some other 393a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * device that doesn't provide one, we can create it as android<n> where <n> is system time. 403a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * This would work on a real device as well, but it would be better to use the "real" id if 413a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * it's available 423a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank */ 433a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank static public synchronized String getDeviceId(Context context) throws IOException { 443a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (sDeviceId == null) { 453a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank sDeviceId = getDeviceIdInternal(context); 463a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 473a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank return sDeviceId; 483a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 493a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 503a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank static private String getDeviceIdInternal(Context context) throws IOException { 513a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (context == null) { 523a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank throw new IllegalStateException("getDeviceId requires a Context"); 533a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 543a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank File f = context.getFileStreamPath("deviceName"); 553a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank BufferedReader rdr = null; 563a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank String id; 573a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (f.exists()) { 583a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (f.canRead()) { 593a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank rdr = new BufferedReader(new FileReader(f), 128); 603a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank id = rdr.readLine(); 613a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank rdr.close(); 62a6de89e79ca51535f92e38cd7b87fdfe32425c77Marc Blank if (id == null) { 63a6de89e79ca51535f92e38cd7b87fdfe32425c77Marc Blank // It's very bad if we read a null device id; let's delete that file 64a6de89e79ca51535f92e38cd7b87fdfe32425c77Marc Blank if (!f.delete()) { 65560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.e(Logging.LOG_TAG, 66560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy "Can't delete null deviceName file; try overwrite."); 67a6de89e79ca51535f92e38cd7b87fdfe32425c77Marc Blank } 68185fd5b3b8251858f0cfad0c180eefebcb38b801Marc Blank } else { 69185fd5b3b8251858f0cfad0c180eefebcb38b801Marc Blank return id; 70a6de89e79ca51535f92e38cd7b87fdfe32425c77Marc Blank } 713a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } else { 72560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.w(Logging.LOG_TAG, f.getAbsolutePath() + ": File exists, but can't read?" + 733a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank " Trying to remove."); 743a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (!f.delete()) { 75560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.w(Logging.LOG_TAG, "Remove failed. Tring to overwrite."); 763a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 773a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 783a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 793a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank BufferedWriter w = new BufferedWriter(new FileWriter(f), 128); 803a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank final String consistentDeviceId = getConsistentDeviceId(context); 813a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (consistentDeviceId != null) { 823a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank // Use different prefix from random IDs. 833a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank id = "androidc" + consistentDeviceId; 843a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } else { 853a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank id = "android" + System.currentTimeMillis(); 863a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 873a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank w.write(id); 883a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank w.close(); 893a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank return id; 903a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 913a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank 923a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank /** 933a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank * @return Device's unique ID if available. null if the device has no unique ID. 943a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank */ 953a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank public static String getConsistentDeviceId(Context context) { 963a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank final String deviceId; 973a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank try { 983a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank TelephonyManager tm = 993a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 1003a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (tm == null) { 1013a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank return null; 1023a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 1033a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank deviceId = tm.getDeviceId(); 1043a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank if (deviceId == null) { 1053a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank return null; 1063a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 1073a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } catch (Exception e) { 108560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.d(Logging.LOG_TAG, "Error in TelephonyManager.getDeviceId(): " 109560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy + e.getMessage()); 1103a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank return null; 1113a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 1123a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank return Utility.getSmallHash(deviceId); 1133a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank } 1143a5c1fb274a9ce72d708d88509bf2607cb018dddMarc Blank} 115