Skip to content

Commit 521f6b3

Browse files
André LagoAndroid (Google) Code Review
authored andcommitted
Merge "Display failed password attempt times for manager" into ub-testdpc-nyc
2 parents 57de73c + a55f870 commit 521f6b3

File tree

1 file changed

+92
-2
lines changed

1 file changed

+92
-2
lines changed

app/src/main/java/com/afwsamples/testdpc/DeviceAdminReceiver.java

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
import android.accounts.Account;
2020
import android.accounts.AccountManager;
2121
import android.annotation.TargetApi;
22-
import android.app.admin.DevicePolicyManager;
2322
import android.app.Notification;
2423
import android.app.NotificationManager;
2524
import android.app.PendingIntent;
25+
import android.app.admin.DevicePolicyManager;
2626
import android.content.ComponentName;
2727
import android.content.Context;
2828
import android.content.Intent;
@@ -40,18 +40,25 @@
4040
import android.util.Log;
4141
import android.widget.Toast;
4242

43-
import com.afwsamples.testdpc.common.Util;
4443
import com.afwsamples.testdpc.common.LaunchIntentUtil;
4544
import com.afwsamples.testdpc.common.Util;
4645
import com.afwsamples.testdpc.cosu.EnableCosuActivity;
4746

47+
import java.io.BufferedReader;
48+
import java.io.BufferedWriter;
4849
import java.io.File;
4950
import java.io.FileInputStream;
5051
import java.io.FileOutputStream;
5152
import java.io.IOException;
5253
import java.io.InputStream;
54+
import java.io.InputStreamReader;
5355
import java.io.OutputStream;
56+
import java.io.OutputStreamWriter;
57+
import java.text.DateFormat;
58+
import java.text.SimpleDateFormat;
5459
import java.util.ArrayList;
60+
import java.util.Collections;
61+
import java.util.Date;
5562
import java.util.List;
5663

5764
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
@@ -67,6 +74,11 @@ public class DeviceAdminReceiver extends android.app.admin.DeviceAdminReceiver {
6774
public static final String ACTION_PASSWORD_REQUIREMENTS_CHANGED =
6875
"com.afwsamples.testdpc.policy.PASSWORD_REQUIREMENTS_CHANGED";
6976

77+
private static final String LOGS_DIR = "logs";
78+
79+
private static final String FAILED_PASSWORD_LOG_FILE =
80+
"failed_pw_attempts_timestamps.log";
81+
7082
private static final int CHANGE_PASSWORD_NOTIFICATION_ID = 101;
7183
private static final int PASSWORD_FAILED_NOTIFICATION_ID = 102;
7284

@@ -360,6 +372,17 @@ public void onPasswordFailed(Context context, Intent intent) {
360372

361373
String title = context.getResources().getQuantityString(
362374
R.plurals.password_failed_attempts_title, attempts, attempts);
375+
376+
ArrayList<Date> previousFailedAttempts = getFailedPasswordAttempts(context);
377+
Date date = new Date();
378+
previousFailedAttempts.add(date);
379+
Collections.sort(previousFailedAttempts, Collections.<Date>reverseOrder());
380+
try {
381+
saveFailedPasswordAttempts(context, previousFailedAttempts);
382+
} catch (IOException e) {
383+
Log.e(TAG, "Unable to save failed password attempts", e);
384+
}
385+
363386
String content = maxAttempts == 0
364387
? context.getString(R.string.password_failed_no_limit_set)
365388
: context.getResources().getQuantityString(
@@ -373,11 +396,78 @@ public void onPasswordFailed(Context context, Intent intent) {
373396
.setContentIntent(PendingIntent.getActivity(context, /* requestCode */ -1,
374397
new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD), /* flags */ 0));
375398

399+
Notification.InboxStyle inboxStyle = new Notification.InboxStyle();
400+
inboxStyle.setBigContentTitle(title);
401+
402+
final DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance();
403+
for(Date d : previousFailedAttempts) {
404+
inboxStyle.addLine(dateFormat.format(d));
405+
}
406+
warn.setStyle(inboxStyle);
407+
376408
NotificationManager nm = (NotificationManager)
377409
context.getSystemService(Context.NOTIFICATION_SERVICE);
378410
nm.notify(PASSWORD_FAILED_NOTIFICATION_ID, warn.getNotification());
379411
}
380412

413+
private static File logFile(Context context) {
414+
File parent = context.getDir(LOGS_DIR, Context.MODE_PRIVATE);
415+
return new File(parent, FAILED_PASSWORD_LOG_FILE);
416+
}
417+
418+
private static ArrayList<Date> getFailedPasswordAttempts(Context context) {
419+
File logFile = logFile(context);
420+
ArrayList<Date> result = new ArrayList<Date>();
421+
422+
if(!logFile.exists()) {
423+
return result;
424+
}
425+
426+
FileInputStream fis = null;
427+
try {
428+
fis = new FileInputStream(logFile);
429+
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
430+
431+
String line = null;
432+
while ((line = br.readLine()) != null && line.length() > 0) {
433+
result.add(new Date(Long.parseLong(line)));
434+
}
435+
436+
br.close();
437+
} catch (IOException e) {
438+
Log.e(TAG, "Unable to read failed password attempts", e);
439+
} finally {
440+
if(fis != null) {
441+
try {
442+
fis.close();
443+
} catch (IOException e) {
444+
Log.e(TAG, "Unable to close failed password attempts log file", e);
445+
}
446+
}
447+
}
448+
449+
return result;
450+
}
451+
452+
private static void saveFailedPasswordAttempts(Context context, ArrayList<Date> attempts)
453+
throws IOException {
454+
File logFile = logFile(context);
455+
456+
if(!logFile.exists()) {
457+
logFile.createNewFile();
458+
}
459+
460+
FileOutputStream fos = new FileOutputStream(logFile);
461+
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
462+
463+
for(Date date : attempts) {
464+
bw.write(Long.toString(date.getTime()));
465+
bw.newLine();
466+
}
467+
468+
bw.close();
469+
}
470+
381471
@Override
382472
public void onPasswordChanged(Context context, Intent intent) {
383473
updatePasswordQualityNotification(context);

0 commit comments

Comments
 (0)