1 /* 2 /* 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.android.emailcommon; 19 20 import android.content.Context; 21 import android.telephony.TelephonyManager; 22 import android.util.Log; 23 24 import com.android.emailcommon.utility.Utility; 25 26 import java.io.BufferedReader; 27 import java.io.BufferedWriter; 28 import java.io.File; 29 import java.io.FileReader; 30 import java.io.FileWriter; 31 import java.io.IOException; 32 33 public class Device { 34 private static String sDeviceId = null; 35 36 /** 37 * EAS requires a unique device id, so that sync is possible from a variety of different 38 * devices (e.g. the syncKey is specific to a device) If we're on an emulator or some other 39 * device that doesn't provide one, we can create it as android<n> where <n> is system time. 40 * This would work on a real device as well, but it would be better to use the "real" id if 41 * it's available 42 */ getDeviceId(Context context)43 static public synchronized String getDeviceId(Context context) throws IOException { 44 if (sDeviceId == null) { 45 sDeviceId = getDeviceIdInternal(context); 46 } 47 return sDeviceId; 48 } 49 getDeviceIdInternal(Context context)50 static private String getDeviceIdInternal(Context context) throws IOException { 51 if (context == null) { 52 throw new IllegalStateException("getDeviceId requires a Context"); 53 } 54 File f = context.getFileStreamPath("deviceName"); 55 BufferedReader rdr = null; 56 String id; 57 if (f.exists()) { 58 if (f.canRead()) { 59 rdr = new BufferedReader(new FileReader(f), 128); 60 id = rdr.readLine(); 61 rdr.close(); 62 if (id == null) { 63 // It's very bad if we read a null device id; let's delete that file 64 if (!f.delete()) { 65 Log.e(Logging.LOG_TAG, "Can't delete null deviceName file; try overwrite."); 66 } 67 } else { 68 return id; 69 } 70 } else { 71 Log.w(Logging.LOG_TAG, f.getAbsolutePath() + ": File exists, but can't read?" + 72 " Trying to remove."); 73 if (!f.delete()) { 74 Log.w(Logging.LOG_TAG, "Remove failed. Tring to overwrite."); 75 } 76 } 77 } 78 BufferedWriter w = new BufferedWriter(new FileWriter(f), 128); 79 final String consistentDeviceId = getConsistentDeviceId(context); 80 if (consistentDeviceId != null) { 81 // Use different prefix from random IDs. 82 id = "androidc" + consistentDeviceId; 83 } else { 84 id = "android" + System.currentTimeMillis(); 85 } 86 w.write(id); 87 w.close(); 88 return id; 89 } 90 91 /** 92 * @return Device's unique ID if available. null if the device has no unique ID. 93 */ getConsistentDeviceId(Context context)94 public static String getConsistentDeviceId(Context context) { 95 final String deviceId; 96 try { 97 TelephonyManager tm = 98 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 99 if (tm == null) { 100 return null; 101 } 102 deviceId = tm.getDeviceId(); 103 if (deviceId == null) { 104 return null; 105 } 106 } catch (Exception e) { 107 Log.d(Logging.LOG_TAG, "Error in TelephonyManager.getDeviceId(): " + e.getMessage()); 108 return null; 109 } 110 return Utility.getSmallHash(deviceId); 111 } 112 } 113