Skip to content

Commit 3958a34

Browse files
committed
Handle Edge Cases and initial tests
1 parent f2a5835 commit 3958a34

4 files changed

Lines changed: 163 additions & 36 deletions

File tree

android/sdl_android/src/androidTest/java/com/smartdevicelink/managers/SdlManagerTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.smartdevicelink.transport.BaseTransportConfig;
2626
import com.smartdevicelink.transport.TCPTransportConfig;
2727

28+
import org.mockito.Mockito;
2829
import org.mockito.invocation.InvocationOnMock;
2930
import org.mockito.stubbing.Answer;
3031

@@ -60,6 +61,8 @@ public class SdlManagerTests extends AndroidTestCase2 {
6061
public void setUp() throws Exception{
6162
super.setUp();
6263

64+
mTestContext = Mockito.mock(Context.class);
65+
6366
// set transport
6467
transport = new TCPTransportConfig(TCP_PORT, DEV_MACHINE_IP_ADDRESS, true);
6568

@@ -125,6 +128,7 @@ public LifecycleConfigurationUpdate managerShouldUpdateLifecycle(Language langua
125128
builder.setLockScreenConfig(lockScreenConfig);
126129
builder.setMinimumProtocolVersion(Test.GENERAL_VERSION);
127130
builder.setMinimumRPCVersion(Test.GENERAL_VERSION);
131+
builder.setContext(mTestContext);
128132
manager = builder.build();
129133

130134
// mock SdlProxyBase and set it manually
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.smartdevicelink.managers.lockscreen;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
6+
import com.smartdevicelink.AndroidTestCase2;
7+
8+
import org.json.JSONException;
9+
import org.json.JSONObject;
10+
import org.mockito.Mockito;
11+
12+
import static org.mockito.ArgumentMatchers.anyInt;
13+
import static org.mockito.ArgumentMatchers.anyString;
14+
import static org.mockito.ArgumentMatchers.isNull;
15+
16+
public class LockScreenDeviceIconManagerTests extends AndroidTestCase2 {
17+
18+
private LockScreenDeviceIconManager lockScreenDeviceIconManager;
19+
private static final String ICON_URL = "http://i.imgur.com/TgkvOIZ.png";
20+
private static final String LAST_UPDATED_TIME = "lastUpdatedTime";
21+
private static final String STORED_URL = "storedUrl";
22+
private static final String INVALID_JSON_STRING = "Invalid JSON";
23+
24+
public void setup() throws Exception {
25+
super.setUp();
26+
}
27+
28+
public void tearDown() throws Exception {
29+
super.tearDown();
30+
}
31+
32+
public void testShouldReturnTrueWhenSharedPreferencesDoesNotExist() {
33+
final SharedPreferences sharedPrefs = Mockito.mock(SharedPreferences.class);
34+
final Context context = Mockito.mock(Context.class);
35+
Mockito.when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
36+
Mockito.when(sharedPrefs.getString(anyString(), (String) isNull())).thenReturn(null);
37+
38+
lockScreenDeviceIconManager = new LockScreenDeviceIconManager(context);
39+
boolean shouldUpdate = lockScreenDeviceIconManager.updateCachedImage(ICON_URL);
40+
assertTrue(shouldUpdate);
41+
}
42+
43+
public void testShouldReturnTrueWhenUnableToReadSharedPreference() {
44+
final SharedPreferences sharedPrefs = Mockito.mock(SharedPreferences.class);
45+
final Context context = Mockito.mock(Context.class);
46+
Mockito.when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
47+
Mockito.when(sharedPrefs.getString(anyString(), (String) isNull())).thenReturn(INVALID_JSON_STRING);
48+
49+
50+
lockScreenDeviceIconManager = new LockScreenDeviceIconManager(context);
51+
boolean shouldUpdate = lockScreenDeviceIconManager.updateCachedImage(ICON_URL);
52+
assertTrue(shouldUpdate);
53+
}
54+
55+
public void testShouldReturnTrueSharedPreferenceReturnsAnOutdatedIcon() {
56+
final SharedPreferences sharedPrefs = Mockito.mock(SharedPreferences.class);
57+
final Context context = Mockito.mock(Context.class);
58+
Mockito.when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
59+
Mockito.when(sharedPrefs.getString(anyString(), (String) isNull())).thenReturn(buildJSONAsString(35));
60+
61+
lockScreenDeviceIconManager = new LockScreenDeviceIconManager(context);
62+
boolean shouldUpdate = lockScreenDeviceIconManager.updateCachedImage(ICON_URL);
63+
assertTrue(shouldUpdate);
64+
}
65+
66+
public void testShouldReturnFalseWhenSharedPreferenceReturnsAnUpdatedIcon() {
67+
final SharedPreferences sharedPrefs = Mockito.mock(SharedPreferences.class);
68+
final Context context = Mockito.mock(Context.class);
69+
Mockito.when(context.getSharedPreferences(anyString(), anyInt())).thenReturn(sharedPrefs);
70+
Mockito.when(sharedPrefs.getString(anyString(), (String) isNull())).thenReturn(buildJSONAsString(15));
71+
72+
lockScreenDeviceIconManager = new LockScreenDeviceIconManager(context);
73+
boolean shouldUpdate = lockScreenDeviceIconManager.updateCachedImage(ICON_URL);
74+
assertFalse(shouldUpdate);
75+
}
76+
77+
private String buildJSONAsString(long DaysOld) {
78+
JSONObject jsonObject = new JSONObject();
79+
try {
80+
jsonObject.put(STORED_URL, "STORED_URL");
81+
long timeDifferenceInMilliSeconds = DaysOld * 1000 * 60 * 60 * 24;
82+
jsonObject.put(LAST_UPDATED_TIME, System.currentTimeMillis() - timeDifferenceInMilliSeconds);
83+
return jsonObject.toString();
84+
} catch (JSONException e) {
85+
e.printStackTrace();
86+
return null;
87+
}
88+
}
89+
90+
91+
}

android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenDeviceIconManager.java

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
class LockScreenDeviceIconManager {
2020

2121
private Context context;
22-
protected static final String SDL_DEVICE_STATUS_SHARED_PREFS = "sdl";
22+
private static final String SDL_DEVICE_STATUS_SHARED_PREFS = "sdl.lockScreenIcon";
23+
private static final String STORED_ICON_PATH = "sdl/lock_screen_icon/";
2324
private static final String LAST_UPDATED_TIME = "lastUpdatedTime";
2425
private static final String STORED_URL = "storedUrl";
2526
private static final String TAG = "LockScreenManager";
2627

2728

2829
LockScreenDeviceIconManager(Context context) {
2930
this.context = context;
31+
File lockScreenDirectory = new File(context.getCacheDir(), STORED_ICON_PATH);
32+
lockScreenDirectory.mkdirs();
3033
}
3134

3235
boolean updateCachedImage(String iconUrl) {
@@ -49,7 +52,6 @@ boolean updateCachedImage(String iconUrl) {
4952
long daysBetweenLastUpdate = timeDifference / (1000 * 60 * 60 * 24);
5053
Log.d(TAG, "Time since last update: " + daysBetweenLastUpdate);
5154
return daysBetweenLastUpdate >= 30;
52-
5355
} catch (JSONException e) {
5456
e.printStackTrace();
5557
Log.d(TAG, "Exception Trying to read system preferences");
@@ -62,46 +64,33 @@ void saveFileToCache(Bitmap icon, String iconUrl) {
6264

6365
String iconHash = getMD5HashFromIconUrl(iconUrl);
6466

65-
File f = new File(this.context.getCacheDir(), iconHash);
66-
try {
67-
Log.d(TAG, "Attempting to save to cache");
68-
ByteArrayOutputStream bos = new ByteArrayOutputStream();
69-
icon.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
70-
byte[] bitmapdata = bos.toByteArray();
67+
File f = new File(this.context.getCacheDir() + "/" + STORED_ICON_PATH, iconHash);
68+
Log.d(TAG, "Attempting to save to cache");
69+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
70+
icon.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
71+
byte[] bitmapdata = bos.toByteArray();
7172

72-
FileOutputStream fos = null;
73+
FileOutputStream fos = null;
74+
try {
7375
fos = new FileOutputStream(f);
7476
fos.write(bitmapdata);
7577
fos.flush();
7678
fos.close();
77-
JSONObject iconParams;
78-
79-
Log.d(TAG, "Attempting to save to system preferences");
80-
iconParams = buildDeviceIconParameters(f.getAbsolutePath());
81-
writeDeviceIconParametersToSystemPreferences(iconHash, iconParams);
8279
} catch (Exception e) {
83-
Log.d(TAG, "Failed to save to cache or system preferences");
80+
Log.d(TAG, "Failed to save to Icon to Cache");
8481
e.printStackTrace();
8582
}
86-
}
8783

88-
private String getMD5HashFromIconUrl(String iconUrl) {
89-
String iconHash = null;
84+
JSONObject iconParams;
85+
Log.d(TAG, "Attempting to save to system preferences");
9086
try {
91-
MessageDigest md = MessageDigest.getInstance("MD5");
92-
byte[] messageDigest = md.digest(iconUrl.getBytes());
93-
BigInteger no = new BigInteger(1, messageDigest);
94-
String hashtext = no.toString(16);
95-
while (hashtext.length() < 32) {
96-
hashtext = "0" + hashtext;
97-
}
98-
iconHash = hashtext;
99-
} catch (NoSuchAlgorithmException e) {
100-
Log.d(TAG, "Unable to Hash URL");
87+
iconParams = buildDeviceIconParameters(f.getAbsolutePath());
88+
writeDeviceIconParametersToSystemPreferences(iconHash, iconParams);
89+
} catch (JSONException e) {
90+
Log.d(TAG, "Failed to save to system preferences, clearing cache icon directory");
91+
clearIconDirectory();
10192
e.printStackTrace();
10293
}
103-
Log.d(TAG, "icon hash: " + iconHash);
104-
return iconHash;
10594
}
10695

10796
Bitmap getFileFromCache(String iconUrl) {
@@ -116,9 +105,17 @@ Bitmap getFileFromCache(String iconUrl) {
116105
Log.d(TAG, "Attempting to get file from cache");
117106
jsonObject = new JSONObject(iconParameters);
118107
String storedUrl = jsonObject.getString(STORED_URL);
119-
return BitmapFactory.decodeFile(storedUrl);
108+
Bitmap cachedIcon = BitmapFactory.decodeFile(storedUrl);
109+
if(cachedIcon == null) {
110+
Log.d(TAG, "Failed to get Bitmap from decoding file cache");
111+
clearIconDirectory();
112+
return null;
113+
} else {
114+
return cachedIcon;
115+
}
120116
} catch (JSONException e) {
121-
Log.d(TAG, "Failed to get file from cache");
117+
Log.d(TAG, "Failed to get file from cache, removing from shared pref");
118+
sharedPref.edit().remove(iconHash).commit();
122119
e.printStackTrace();
123120
return null;
124121
}
@@ -143,4 +140,30 @@ private JSONObject buildDeviceIconParameters(String storedUrl) throws JSONExcept
143140
parametersJson.put(LAST_UPDATED_TIME, System.currentTimeMillis());
144141
return parametersJson;
145142
}
143+
144+
private String getMD5HashFromIconUrl(String iconUrl) {
145+
String iconHash = null;
146+
try {
147+
MessageDigest md = MessageDigest.getInstance("MD5");
148+
byte[] messageDigest = md.digest(iconUrl.getBytes());
149+
BigInteger no = new BigInteger(1, messageDigest);
150+
String hashtext = no.toString(16);
151+
while (hashtext.length() < 32) {
152+
hashtext = "0" + hashtext;
153+
}
154+
iconHash = hashtext;
155+
} catch (NoSuchAlgorithmException e) {
156+
Log.d(TAG, "Unable to Hash URL");
157+
e.printStackTrace();
158+
}
159+
Log.d(TAG, "icon hash: " + iconHash);
160+
return iconHash;
161+
}
162+
163+
private void clearIconDirectory() {
164+
File iconDir = new File(context.getCacheDir() + "/" + STORED_ICON_PATH);
165+
for (File child : iconDir.listFiles()) {
166+
child.delete();
167+
}
168+
}
146169
}

android/sdl_android/src/main/java/com/smartdevicelink/managers/lockscreen/LockScreenManager.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,24 +380,33 @@ private void downloadDeviceIcon(final String url){
380380
public void run(){
381381
try{
382382
if(mLockScreenDeviceIconManager.updateCachedImage(url)) {
383+
Log.d(TAG, "URL: " + url);
383384
Log.d(TAG, "Image Update Needed");
384385
deviceLogo = AndroidTools.downloadImage(url);
385386
mLockScreenDeviceIconManager.saveFileToCache(deviceLogo, url);
386387
} else {
387388
Log.d(TAG, "Image Is Up To Date");
388389
deviceLogo = mLockScreenDeviceIconManager.getFileFromCache(url);
390+
if (deviceLogo == null) {
391+
deviceLogo = AndroidTools.downloadImage(url);
392+
mLockScreenDeviceIconManager.saveFileToCache(deviceLogo, url);
393+
}
389394
}
390-
395+
} catch(IOException e){
396+
Log.e(TAG, "device Icon Error Downloading");
397+
Log.e(TAG, e.toString());
398+
Log.e(TAG, "Attempt to grab Cached image even if expired");
399+
deviceLogo = mLockScreenDeviceIconManager.getFileFromCache(url);
400+
}
401+
if(deviceLogo != null) {
391402
Intent intent = new Intent(SDLLockScreenActivity.LOCKSCREEN_DEVICE_LOGO_DOWNLOADED);
392403
intent.putExtra(SDLLockScreenActivity.LOCKSCREEN_DEVICE_LOGO_EXTRA, deviceLogoEnabled);
393404
intent.putExtra(SDLLockScreenActivity.LOCKSCREEN_DEVICE_LOGO_BITMAP, deviceLogo);
394405
if (context.get() != null) {
395406
context.get().sendBroadcast(intent);
396407
}
397-
}catch(IOException e){
398-
Log.e(TAG, "device Icon Error Downloading");
399-
Log.e(TAG, e.toString());
400408
}
409+
401410
}
402411
}).start();
403412
}

0 commit comments

Comments
 (0)