Skip to content

Commit 79db80f

Browse files
committed
Upstream 3.0.9 source
2 parents 2b1427a + ace8ca4 commit 79db80f

17 files changed

+511
-122
lines changed

app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ext {
77
// exactly 1 digit
88
versionMinor = 0
99
// exactly 2 digits
10-
versionBuild = 8
10+
versionBuild = 9
1111
}
1212

1313
android {
@@ -58,7 +58,7 @@ android {
5858
}
5959

6060
dependencies {
61-
compile 'com.android.support:preference-v14:24+'
61+
compile 'com.android.support:preference-v14:24.0.0'
6262
compile 'com.android.support:recyclerview-v7:24.+'
6363
compile "com.android.support:support-v13:24.+"
6464
compile 'com.google.android.gms:play-services-safetynet:+'

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import android.view.View;
3232
import android.widget.EditText;
3333
import android.widget.RadioGroup;
34+
import android.widget.Toast;
3435

3536
import com.android.setupwizardlib.SetupWizardLayout;
3637
import com.android.setupwizardlib.view.NavigationBar;
@@ -58,6 +59,8 @@ protected void onCreate(Bundle savedInstanceState) {
5859
setContentView(R.layout.activity_add_account);
5960
SetupWizardLayout layout = (SetupWizardLayout) findViewById(R.id.setup_wizard_layout);
6061
layout.getNavigationBar().setNavigationBarListener(this);
62+
NavigationBar navigationBar = layout.getNavigationBar();
63+
navigationBar.getBackButton().setEnabled(false);
6164

6265
Bundle extras = getIntent().getExtras();
6366
if (extras != null) {
@@ -92,6 +95,9 @@ public void run(AccountManagerFuture<Bundle> accountManagerFuture) {
9295
} catch (OperationCanceledException | AuthenticatorException
9396
| IOException e) {
9497
Log.e(TAG, "addAccount - failed", e);
98+
Toast.makeText(AddAccountActivity.this,
99+
R.string.fail_to_add_account, Toast.LENGTH_LONG).show();
100+
return;
95101
}
96102
Log.d(TAG, "addAccount - isAccountAdded: " + isAccountAdded
97103
+ ", accountNameAdded: " + accountNameAdded);
@@ -134,7 +140,5 @@ public void onClick(DialogInterface dialogInterface, int i) {
134140
}
135141

136142
@Override
137-
public void onNavigateBack() {
138-
onBackPressed();
139-
}
143+
public void onNavigateBack() {}
140144
}

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

+104-8
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616

1717
package com.afwsamples.testdpc;
1818

19+
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
20+
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
21+
import static com.afwsamples.testdpc.policy.PolicyManagementFragment.OVERRIDE_KEY_SELECTION_KEY;
22+
1923
import android.accounts.Account;
2024
import android.accounts.AccountManager;
2125
import android.annotation.TargetApi;
22-
import android.app.admin.DevicePolicyManager;
2326
import android.app.Notification;
2427
import android.app.NotificationManager;
2528
import android.app.PendingIntent;
29+
import android.app.admin.DevicePolicyManager;
2630
import android.content.ComponentName;
2731
import android.content.Context;
2832
import android.content.Intent;
@@ -40,24 +44,27 @@
4044
import android.util.Log;
4145
import android.widget.Toast;
4246

43-
import com.afwsamples.testdpc.common.Util;
4447
import com.afwsamples.testdpc.common.LaunchIntentUtil;
4548
import com.afwsamples.testdpc.common.Util;
4649
import com.afwsamples.testdpc.cosu.EnableCosuActivity;
4750

51+
import java.io.BufferedReader;
52+
import java.io.BufferedWriter;
4853
import java.io.File;
4954
import java.io.FileInputStream;
5055
import java.io.FileOutputStream;
5156
import java.io.IOException;
5257
import java.io.InputStream;
58+
import java.io.InputStreamReader;
5359
import java.io.OutputStream;
60+
import java.io.OutputStreamWriter;
61+
import java.text.DateFormat;
62+
import java.text.SimpleDateFormat;
5463
import java.util.ArrayList;
64+
import java.util.Collections;
65+
import java.util.Date;
5566
import java.util.List;
5667

57-
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
58-
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
59-
import static com.afwsamples.testdpc.policy.PolicyManagementFragment.OVERRIDE_KEY_SELECTION_KEY;
60-
6168
/**
6269
* Handles events related to the managed profile.
6370
*/
@@ -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

@@ -297,8 +309,14 @@ private boolean isRuntimePermission(PackageManager packageManager, String permis
297309
@TargetApi(Build.VERSION_CODES.M)
298310
@Override
299311
public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
300-
Toast.makeText(context, "System update received at: " + receivedTime,
301-
Toast.LENGTH_LONG).show();
312+
if (receivedTime != -1) {
313+
DateFormat sdf = new SimpleDateFormat("hh:mm:ss dd/MM/yyyy");
314+
String timeString = sdf.format(new Date(receivedTime));
315+
Toast.makeText(context, "System update received at: " + timeString,
316+
Toast.LENGTH_LONG).show();
317+
} else {
318+
// No system update is currently available on this device.
319+
}
302320
}
303321

304322
@TargetApi(Build.VERSION_CODES.M)
@@ -360,6 +378,17 @@ public void onPasswordFailed(Context context, Intent intent) {
360378

361379
String title = context.getResources().getQuantityString(
362380
R.plurals.password_failed_attempts_title, attempts, attempts);
381+
382+
ArrayList<Date> previousFailedAttempts = getFailedPasswordAttempts(context);
383+
Date date = new Date();
384+
previousFailedAttempts.add(date);
385+
Collections.sort(previousFailedAttempts, Collections.<Date>reverseOrder());
386+
try {
387+
saveFailedPasswordAttempts(context, previousFailedAttempts);
388+
} catch (IOException e) {
389+
Log.e(TAG, "Unable to save failed password attempts", e);
390+
}
391+
363392
String content = maxAttempts == 0
364393
? context.getString(R.string.password_failed_no_limit_set)
365394
: context.getResources().getQuantityString(
@@ -373,11 +402,78 @@ public void onPasswordFailed(Context context, Intent intent) {
373402
.setContentIntent(PendingIntent.getActivity(context, /* requestCode */ -1,
374403
new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD), /* flags */ 0));
375404

405+
Notification.InboxStyle inboxStyle = new Notification.InboxStyle();
406+
inboxStyle.setBigContentTitle(title);
407+
408+
final DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance();
409+
for(Date d : previousFailedAttempts) {
410+
inboxStyle.addLine(dateFormat.format(d));
411+
}
412+
warn.setStyle(inboxStyle);
413+
376414
NotificationManager nm = (NotificationManager)
377415
context.getSystemService(Context.NOTIFICATION_SERVICE);
378416
nm.notify(PASSWORD_FAILED_NOTIFICATION_ID, warn.getNotification());
379417
}
380418

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

app/src/main/java/com/afwsamples/testdpc/common/ProfileOrParentFragment.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ public void onCreate(Bundle savedInstanceState) {
169169
mProfileOwner = mDevicePolicyManager.isProfileOwnerApp(getActivity().getPackageName());
170170
mDeviceOwner = mDevicePolicyManager.isDeviceOwnerApp(getActivity().getPackageName());
171171

172+
if (mParentInstance) {
173+
mDevicePolicyManager = mDevicePolicyManager.getParentProfileInstance(mAdminComponent);
174+
}
175+
172176
// Put at last to make sure all initializations above are done before subclass's
173177
// onCreatePreferences is called.
174178
super.onCreate(savedInstanceState);
@@ -177,7 +181,6 @@ public void onCreate(Bundle savedInstanceState) {
177181
// This needs to be called after super.onCreate because preference manager is set up
178182
// inside super.onCreate.
179183
if (mParentInstance) {
180-
mDevicePolicyManager = mDevicePolicyManager.getParentProfileInstance(mAdminComponent);
181184
final PreferenceManager pm = getPreferenceManager();
182185
pm.setSharedPreferencesName(pm.getSharedPreferencesName() + TAG_PARENT);
183186
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright (C) 2016 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.afwsamples.testdpc.common;
18+
19+
import android.annotation.TargetApi;
20+
import android.content.RestrictionEntry;
21+
import android.os.Build;
22+
import android.os.Bundle;
23+
import android.util.Log;
24+
25+
import java.util.Arrays;
26+
import java.util.List;
27+
28+
/**
29+
* Ported from {@link android.content.RestrictionsManager}.
30+
*/
31+
public class RestrictionManagerCompat {
32+
private static final String TAG = "RestrictionManager";
33+
34+
/**
35+
* Converts a list of restrictions to the corresponding bundle, using the following mapping:
36+
* <table>
37+
* <tr><th>RestrictionEntry</th><th>Bundle</th></tr>
38+
* <tr><td>{@link RestrictionEntry#TYPE_BOOLEAN}</td><td>{@link Bundle#putBoolean}</td></tr>
39+
* <tr><td>{@link RestrictionEntry#TYPE_CHOICE},
40+
* {@link RestrictionEntry#TYPE_MULTI_SELECT}</td>
41+
* <td>{@link Bundle#putStringArray}</td></tr>
42+
* <tr><td>{@link RestrictionEntry#TYPE_INTEGER}</td><td>{@link Bundle#putInt}</td></tr>
43+
* <tr><td>{@link RestrictionEntry#TYPE_STRING}</td><td>{@link Bundle#putString}</td></tr>
44+
* <tr><td>{@link RestrictionEntry#TYPE_BUNDLE}</td><td>{@link Bundle#putBundle}</td></tr>
45+
* <tr><td>{@link RestrictionEntry#TYPE_BUNDLE_ARRAY}</td>
46+
* <td>{@link Bundle#putParcelableArray}</td></tr>
47+
* </table>
48+
* TYPE_BUNDLE and TYPE_BUNDLE_ARRAY are supported from api level 23 onwards.
49+
* @param entries list of restrictions
50+
*/
51+
public static Bundle convertRestrictionsToBundle(List<RestrictionEntry> entries) {
52+
final Bundle bundle = new Bundle();
53+
for (RestrictionEntry entry : entries) {
54+
addRestrictionToBundle(bundle, entry);
55+
}
56+
return bundle;
57+
}
58+
59+
private static Bundle addRestrictionToBundle(Bundle bundle, RestrictionEntry entry) {
60+
switch (entry.getType()) {
61+
case RestrictionEntry.TYPE_BOOLEAN:
62+
bundle.putBoolean(entry.getKey(), entry.getSelectedState());
63+
break;
64+
case RestrictionEntry.TYPE_CHOICE:
65+
case RestrictionEntry.TYPE_MULTI_SELECT:
66+
bundle.putStringArray(entry.getKey(), entry.getAllSelectedStrings());
67+
break;
68+
case RestrictionEntry.TYPE_INTEGER:
69+
bundle.putInt(entry.getKey(), entry.getIntValue());
70+
break;
71+
case RestrictionEntry.TYPE_STRING:
72+
case RestrictionEntry.TYPE_NULL:
73+
bundle.putString(entry.getKey(), entry.getSelectedString());
74+
break;
75+
case RestrictionEntry.TYPE_BUNDLE:
76+
addBundleRestrictionToBundle(bundle, entry);
77+
break;
78+
case RestrictionEntry.TYPE_BUNDLE_ARRAY:
79+
addBundleArrayRestrictionToBundle(bundle, entry);
80+
break;
81+
default:
82+
throw new IllegalArgumentException(
83+
"Unsupported restrictionEntry type: " + entry.getType());
84+
}
85+
return bundle;
86+
}
87+
88+
@TargetApi(Build.VERSION_CODES.M)
89+
private static void addBundleRestrictionToBundle(Bundle bundle, RestrictionEntry entry) {
90+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
91+
RestrictionEntry[] restrictions = entry.getRestrictions();
92+
Bundle childBundle = convertRestrictionsToBundle(Arrays.asList(restrictions));
93+
bundle.putBundle(entry.getKey(), childBundle);
94+
} else {
95+
Log.w(TAG, "addBundleRestrictionToBundle is called in pre-M");
96+
}
97+
}
98+
99+
@TargetApi(Build.VERSION_CODES.M)
100+
private static void addBundleArrayRestrictionToBundle(Bundle bundle, RestrictionEntry entry) {
101+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
102+
RestrictionEntry[] bundleRestrictionArray = entry.getRestrictions();
103+
Bundle[] bundleArray = new Bundle[bundleRestrictionArray.length];
104+
for (int i = 0; i < bundleRestrictionArray.length; i++) {
105+
RestrictionEntry[] bundleRestrictions =
106+
bundleRestrictionArray[i].getRestrictions();
107+
if (bundleRestrictions == null) {
108+
// Non-bundle entry found in bundle array.
109+
Log.w(TAG, "addRestrictionToBundle: " +
110+
"Non-bundle entry found in bundle array");
111+
bundleArray[i] = new Bundle();
112+
} else {
113+
bundleArray[i] = convertRestrictionsToBundle(Arrays.asList(
114+
bundleRestrictions));
115+
}
116+
}
117+
bundle.putParcelableArray(entry.getKey(), bundleArray);
118+
} else {
119+
Log.w(TAG, "addBundleArrayRestrictionToBundle is called in pre-M");
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)