diff --git a/app/build.gradle b/app/build.gradle
index fbb96074..b8d53032 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,7 +7,7 @@ ext {
// exactly 1 digit
versionMinor = 0
// exactly 2 digits
- versionBuild = 00
+ versionBuild = 01
}
android {
@@ -16,7 +16,7 @@ android {
defaultConfig {
applicationId "com.afwsamples.testdpc"
minSdkVersion 21
- targetSdkVersion 28
+ targetSdkVersion 'P'
versionCode versionMajor * 1000 + versionMinor * 100 + versionBuild
versionName "${versionMajor}.${versionMinor}.${versionBuild}"
multiDexEnabled true
@@ -29,16 +29,8 @@ android {
}
}
- flavorDimensions "targetSdk", "packageName"
+ flavorDimensions "packageName"
productFlavors {
- targetP {
- dimension 'targetSdk'
- targetSdkVersion 'P'
- }
- targetO {
- dimension 'targetSdk'
- targetSdkVersion 27
- }
normal {
dimension 'packageName'
}
@@ -81,11 +73,10 @@ android {
dependencies {
implementation 'com.android.support:multidex:1.0.1'
- implementation 'com.android.support:preference-v14:27.0.2'
- implementation 'com.android.support:recyclerview-v7:27.0.2'
- implementation 'com.android.support:support-v13:27.0.2'
+ implementation 'com.android.support:preference-v14:28.0.0-alpha1'
+ implementation 'com.android.support:recyclerview-v7:28.0.0-alpha1'
+ implementation 'com.android.support:support-v13:28.0.0-alpha1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
- implementation 'com.google.android.gms:play-services-safetynet:+'
implementation(name: 'setup-wizard-lib-platform-release', ext: 'aar')
implementation 'org.bouncycastle:bcpkix-jdk15on:1.56'
implementation 'org.bouncycastle:bcprov-jdk15on:1.56'
diff --git a/app/libs/setup-wizard-lib-platform-release.aar b/app/libs/setup-wizard-lib-platform-release.aar
index 9a50d09d..2e1c3d0d 100644
Binary files a/app/libs/setup-wizard-lib-platform-release.aar and b/app/libs/setup-wizard-lib-platform-release.aar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8e7e2c47..1543b7e7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
-
+
@@ -63,22 +64,17 @@
+ android:theme="@style/SuwThemeGlifV3.Light"/>
-
-
+ android:theme="@style/SuwThemeGlifV3.Light"/>
+ android:theme="@style/SuwThemeGlifV3.Light"/>
-
@@ -121,17 +114,6 @@
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/java/com/afwsamples/testdpc/AddAccountActivity.java b/app/src/main/java/com/afwsamples/testdpc/AddAccountActivity.java
index 7904259f..06169e91 100644
--- a/app/src/main/java/com/afwsamples/testdpc/AddAccountActivity.java
+++ b/app/src/main/java/com/afwsamples/testdpc/AddAccountActivity.java
@@ -35,8 +35,7 @@
import android.widget.RadioGroup;
import android.widget.Toast;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.NavigationBar;
+import com.android.setupwizardlib.GlifLayout;
import java.io.IOException;
@@ -45,7 +44,7 @@
* It is responsible for adding an account to the managed profile (Profile Owner) or managed device
* (Device Owner).
*/
-public class AddAccountActivity extends Activity implements NavigationBar.NavigationBarListener {
+public class AddAccountActivity extends Activity {
private static final String TAG = "AddAccountActivity";
private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
@@ -70,10 +69,8 @@ protected void onCreate(Bundle savedInstanceState) {
mAdminComponentName = DeviceAdminReceiver.getComponentName(this);
setContentView(R.layout.activity_add_account);
- SetupWizardLayout layout = (SetupWizardLayout) findViewById(R.id.setup_wizard_layout);
- layout.getNavigationBar().setNavigationBarListener(this);
- NavigationBar navigationBar = layout.getNavigationBar();
- navigationBar.getBackButton().setEnabled(false);
+ GlifLayout layout = findViewById(R.id.setup_wizard_layout);
+ layout.findViewById(R.id.next_button).setOnClickListener(this::onNavigateNext);
Bundle extras = getIntent().getExtras();
if (extras != null) {
@@ -145,9 +142,8 @@ private void restoreUserRestrictions() {
}
}
- @Override
- public void onNavigateNext() {
- RadioGroup addAccountOptions = (RadioGroup) findViewById(R.id.add_account_options);
+ public void onNavigateNext(View nextButton) {
+ RadioGroup addAccountOptions = findViewById(R.id.add_account_options);
switch (addAccountOptions.getCheckedRadioButtonId()) {
case R.id.add_account:
addAccount(null);
@@ -168,14 +164,10 @@ public void onNavigateNext() {
break;
case R.id.add_account_skip:
if (mNextActivityIntent != null) {
- mNextActivityIntent.putExtra(EnableProfileActivity.EXTRA_ENABLE_PROFILE_NOW, true);
startActivity(mNextActivityIntent);
}
finish();
break;
}
}
-
- @Override
- public void onNavigateBack() {}
}
diff --git a/app/src/main/java/com/afwsamples/testdpc/EnableDeviceOwnerActivity.java b/app/src/main/java/com/afwsamples/testdpc/EnableDeviceOwnerActivity.java
deleted file mode 100644
index 0acfc3fd..00000000
--- a/app/src/main/java/com/afwsamples/testdpc/EnableDeviceOwnerActivity.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.afwsamples.testdpc;
-
-import android.app.Activity;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.afwsamples.testdpc.common.LaunchIntentUtil;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.NavigationBar;
-
-/**
- * This activity is started after device owner provisioning is complete in
- * {@link DeviceAdminReceiver}.
- */
-public class EnableDeviceOwnerActivity extends Activity
- implements NavigationBar.NavigationBarListener {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.enable_device_owner_activity);
- SetupWizardLayout layout = (SetupWizardLayout) findViewById(R.id.setup_wizard_layout);
- NavigationBar navigationBar = layout.getNavigationBar();
- navigationBar.setNavigationBarListener(this);
- navigationBar.getNextButton().setText(R.string.finish_button);
-
- ImageView appIcon = (ImageView) findViewById(R.id.app_icon);
- TextView appLabel = (TextView) findViewById(R.id.app_label);
- try {
- PackageManager packageManager = getPackageManager();
- ApplicationInfo applicationInfo = packageManager.getApplicationInfo(
- getPackageName(), 0 /* Default flags */);
- appIcon.setImageDrawable(packageManager.getApplicationIcon(applicationInfo));
- appLabel.setText(packageManager.getApplicationLabel(applicationInfo));
- } catch (PackageManager.NameNotFoundException e) {
- Log.w("TestDPC", "Couldn't look up our own package?!?!", e);
- }
-
- // Show the user which account now has management, if specified.
- String addedAccount = getIntent().getStringExtra(LaunchIntentUtil.EXTRA_ACCOUNT_NAME);
- if (addedAccount != null) {
- findViewById(R.id.managed_account_name_label).setVisibility(View.VISIBLE);
-
- TextView managedAccountName = (TextView) findViewById(R.id.managed_account_name);
- managedAccountName.setText(addedAccount);
- managedAccountName.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- finish();
- }
-}
diff --git a/app/src/main/java/com/afwsamples/testdpc/EnableProfileActivity.java b/app/src/main/java/com/afwsamples/testdpc/EnableProfileActivity.java
deleted file mode 100644
index 8079e7eb..00000000
--- a/app/src/main/java/com/afwsamples/testdpc/EnableProfileActivity.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.afwsamples.testdpc;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.support.annotation.StringRes;
-import android.support.v4.content.LocalBroadcastManager;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.afwsamples.testdpc.common.LaunchIntentUtil;
-import com.afwsamples.testdpc.provision.CheckInState;
-import com.afwsamples.testdpc.provision.ProvisioningUtil;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.NavigationBar;
-
-import static com.afwsamples.testdpc.provision.CheckInState.FIRST_ACCOUNT_READY_PROCESSED_ACTION;
-
-/**
- * This activity is started after managed profile provisioning is complete in
- * {@link DeviceAdminReceiver}. There could be two cases:
- * 1. If we are not going to add account now, we will then enable profile immediately.
- * 2. If we have just added account, we need to wait for the FIRST_ACCOUNT_READY broadcast before
- * enabling the profile. The broadcast indicates that the account has been synced with Google
- * and is ready for use.
- */
-public class EnableProfileActivity extends Activity implements NavigationBar.NavigationBarListener {
- private CheckInStateReceiver mCheckInStateReceiver;
- private Button mFinishButton;
- private SetupWizardLayout mSetupWizardLayout;
-
- private CheckInState mCheckinState;
-
- public static final String EXTRA_ENABLE_PROFILE_NOW = "enable_profile_now";
- private static final IntentFilter sIntentFilter =
- new IntentFilter(FIRST_ACCOUNT_READY_PROCESSED_ACTION);
- private static final long WAIT_FOR_FIRST_ACCOUNT_READY_TIMEOUT = 60 * 1000;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mCheckinState = new CheckInState(this);
- if (savedInstanceState == null) {
- if (getIntent().getBooleanExtra(EXTRA_ENABLE_PROFILE_NOW, false)) {
- mCheckinState.setFirstAccountState(CheckInState.FIRST_ACCOUNT_STATE_READY);
- ProvisioningUtil.enableProfile(this);
- } else {
- // Set up an alarm to enable profile in case we do not receive first account ready
- // broadcast for whatever reason.
- FirstAccountReadyBroadcastReceiver.scheduleFirstAccountReadyTimeoutAlarm(
- this, WAIT_FOR_FIRST_ACCOUNT_READY_TIMEOUT);
- }
- }
- setContentView(R.layout.enable_profile_activity);
- mSetupWizardLayout = (SetupWizardLayout) findViewById(R.id.setup_wizard_layout);
- NavigationBar navigationBar = mSetupWizardLayout.getNavigationBar();
- navigationBar.getBackButton().setEnabled(false);
- navigationBar.setNavigationBarListener(this);
- mFinishButton = navigationBar.getNextButton();
- mFinishButton.setText(R.string.finish_button);
-
- mCheckInStateReceiver = new CheckInStateReceiver();
-
- // This is just a user friendly shortcut to the policy management screen of this app.
- ImageView appIcon = (ImageView) findViewById(R.id.app_icon);
- TextView appLabel = (TextView) findViewById(R.id.app_label);
- try {
- PackageManager packageManager = getPackageManager();
- ApplicationInfo applicationInfo = packageManager.getApplicationInfo(
- getPackageName(), 0 /* Default flags */);
- appIcon.setImageDrawable(packageManager.getApplicationIcon(applicationInfo));
- appLabel.setText(packageManager.getApplicationLabel(applicationInfo));
- } catch (PackageManager.NameNotFoundException e) {
- Log.w("TestDPC", "Couldn't look up our own package?!?!", e);
- }
-
- // Show the user which account now has management, if specified.
- String addedAccount = getIntent().getStringExtra(LaunchIntentUtil.EXTRA_ACCOUNT_NAME);
- if (addedAccount != null) {
- View accountMigrationStatusLayout;
- if (isAccountMigrated(addedAccount)) {
- accountMigrationStatusLayout = findViewById(R.id.account_migration_success);
- } else {
- accountMigrationStatusLayout = findViewById(R.id.account_migration_fail);
- }
- accountMigrationStatusLayout.setVisibility(View.VISIBLE);
- TextView managedAccountName = (TextView) accountMigrationStatusLayout.findViewById(
- R.id.managed_account_name);
- managedAccountName.setText(addedAccount);
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- LocalBroadcastManager.getInstance(this).registerReceiver(mCheckInStateReceiver,
- sIntentFilter);
- // In case the broadcast is sent before we register the receiver.
- refreshUi();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- LocalBroadcastManager.getInstance(this).unregisterReceiver(mCheckInStateReceiver);
- }
-
- private boolean isAccountMigrated(String addedAccount) {
- Account[] accounts = AccountManager.get(this).getAccounts();
- for (Account account : accounts) {
- if (addedAccount.equalsIgnoreCase(account.name)) {
- return true;
- }
- }
- return false;
- }
-
- private void refreshUi() {
- boolean enableFinish;
- @StringRes int headerTextResId;
- switch (mCheckinState.getFirstAccountState()) {
- case CheckInState.FIRST_ACCOUNT_STATE_READY:
- enableFinish = true;
- headerTextResId = R.string.finish_setup;
- break;
- case CheckInState.FIRST_ACCOUNT_STATE_TIMEOUT:
- enableFinish = true;
- headerTextResId = R.string.finish_setup_account_not_ready;
- break;
- case CheckInState.FIRST_ACCOUNT_STATE_PENDING:
- default:
- enableFinish = false;
- headerTextResId = R.string.waiting_for_first_account_check_in;
- break;
- }
- if (enableFinish) {
- mSetupWizardLayout.hideProgressBar();
- } else {
- mSetupWizardLayout.showProgressBar();
- }
- mSetupWizardLayout.setHeaderText(headerTextResId);
- mFinishButton.setEnabled(enableFinish);
- }
-
- @Override
- public void onNavigateBack() {
- onBackPressed();
- }
-
- @Override
- public void onNavigateNext() {
- finish();
- }
-
- class CheckInStateReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Processed the first check-in broadcast, allow user to tap the finish button.
- refreshUi();
- }
- }
-}
diff --git a/app/src/main/java/com/afwsamples/testdpc/FinalizeActivity.java b/app/src/main/java/com/afwsamples/testdpc/FinalizeActivity.java
new file mode 100644
index 00000000..61140c0c
--- /dev/null
+++ b/app/src/main/java/com/afwsamples/testdpc/FinalizeActivity.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.afwsamples.testdpc;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.Activity;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.afwsamples.testdpc.common.LaunchIntentUtil;
+import com.afwsamples.testdpc.common.Util;
+import com.afwsamples.testdpc.provision.ProvisioningUtil;
+import com.android.setupwizardlib.GlifLayout;
+
+public class FinalizeActivity extends Activity {
+ private Button mFinishButton;
+ private GlifLayout mSetupWizardLayout;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ if (Util.isManagedProfileOwner(this)) {
+ ProvisioningUtil.enableProfile(this);
+ }
+ }
+ setContentView(R.layout.finalize_activity);
+ mSetupWizardLayout = findViewById(R.id.setup_wizard_layout);
+ mFinishButton = mSetupWizardLayout.findViewById(R.id.next_button);
+ mFinishButton.setText(R.string.finish_button);
+ mFinishButton.setOnClickListener(this::onNavigateNext);
+
+
+ // This is just a user friendly shortcut to the policy management screen of this app.
+ ImageView appIcon = findViewById(R.id.app_icon);
+ TextView appLabel = findViewById(R.id.app_label);
+ try {
+ PackageManager packageManager = getPackageManager();
+ ApplicationInfo applicationInfo = packageManager.getApplicationInfo(
+ getPackageName(), 0 /* Default flags */);
+ appIcon.setImageDrawable(packageManager.getApplicationIcon(applicationInfo));
+ appLabel.setText(packageManager.getApplicationLabel(applicationInfo));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w("TestDPC", "Couldn't look up our own package?!?!", e);
+ }
+
+ // Show the user which account now has management, if specified.
+ String addedAccount = getIntent().getStringExtra(LaunchIntentUtil.EXTRA_ACCOUNT_NAME);
+ if (addedAccount != null) {
+ View accountMigrationStatusLayout;
+ if (isAccountMigrated(addedAccount)) {
+ accountMigrationStatusLayout = findViewById(R.id.account_migration_success);
+ } else {
+ accountMigrationStatusLayout = findViewById(R.id.account_migration_fail);
+ }
+ accountMigrationStatusLayout.setVisibility(View.VISIBLE);
+ TextView managedAccountName = (TextView) accountMigrationStatusLayout.findViewById(
+ R.id.managed_account_name);
+ managedAccountName.setText(addedAccount);
+ }
+
+ ((TextView) findViewById(R.id.explanation)).setText(Util.isDeviceOwner(this)
+ ? R.string.all_done_explanation_device_owner
+ : R.string.all_done_explanation_profile_owner);
+ }
+
+ private boolean isAccountMigrated(String addedAccount) {
+ Account[] accounts = AccountManager.get(this).getAccounts();
+ for (Account account : accounts) {
+ if (addedAccount.equalsIgnoreCase(account.name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void onNavigateNext(View nextButton) {
+ finish();
+ }
+}
diff --git a/app/src/main/java/com/afwsamples/testdpc/FirstAccountReadyBroadcastReceiver.java b/app/src/main/java/com/afwsamples/testdpc/FirstAccountReadyBroadcastReceiver.java
deleted file mode 100644
index 61efe57c..00000000
--- a/app/src/main/java/com/afwsamples/testdpc/FirstAccountReadyBroadcastReceiver.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.afwsamples.testdpc;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.afwsamples.testdpc.common.Util;
-import com.afwsamples.testdpc.provision.CheckInState;
-import com.afwsamples.testdpc.provision.ProvisioningUtil;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Receiver for FIRST_ACCOUNT_READY_ACTION from Google Play Service.
- * Receiver only matters for Managed Profile flow, so we ignore the broadcast in other cases.
- */
-public class FirstAccountReadyBroadcastReceiver extends BroadcastReceiver {
- private static final String TAG = "FirstAccountReady";
-
- private static final String FIRST_ACCOUNT_READY_ACTION =
- "com.google.android.work.action.FIRST_ACCOUNT_READY";
-
- public static final String FIRST_ACCOUNT_READY_TIMEOUT_ACTION =
- "com.afwsamples.testdpc.FIRST_ACCOUNT_READY_TIMEOUT";
-
- private static final Set SUPPORTED_ACTIONS = new HashSet<>(
- Arrays.asList(FIRST_ACCOUNT_READY_ACTION, FIRST_ACCOUNT_READY_TIMEOUT_ACTION));
-
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- Log.d(TAG, "Received: " + action);
-
- if (!Util.isManagedProfileOwner(context)) {
- Log.d(TAG, "Not a Managed Profile case. Ignoring broadcast.");
- return;
- }
-
- if (!SUPPORTED_ACTIONS.contains(action)) {
- Log.d(TAG, String.format("Action %s not supported by receiver %s. Ignoring broadcast.",
- action, getClass().getName()));
- return;
- }
-
- CheckInState checkInState = new CheckInState(context);
- if (checkInState.getFirstAccountState() == CheckInState.FIRST_ACCOUNT_STATE_PENDING) {
- checkInState.setFirstAccountState(FIRST_ACCOUNT_READY_ACTION.equals(action)
- ? CheckInState.FIRST_ACCOUNT_STATE_READY
- : CheckInState.FIRST_ACCOUNT_STATE_TIMEOUT);
-
- ProvisioningUtil.enableProfile(context);
- }
- }
-
- /**
- * Enable profile anyway if we cannot receive the broadcast after certain amount time.
- */
- public static void scheduleFirstAccountReadyTimeoutAlarm(Context context, long timeout) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + timeout,
- createFirstAccountReadyTimeoutPendingIntent(context));
- }
-
- public static void cancelFirstAccountReadyTimeoutAlarm(Context context) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarmManager.cancel(createFirstAccountReadyTimeoutPendingIntent(context));
- }
-
- private static PendingIntent createFirstAccountReadyTimeoutPendingIntent(Context context) {
- Intent intent = new Intent(context, FirstAccountReadyBroadcastReceiver.class);
- intent.setAction(FirstAccountReadyBroadcastReceiver.FIRST_ACCOUNT_READY_TIMEOUT_ACTION);
- return PendingIntent.getBroadcast(
- context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/afwsamples/testdpc/SetupManagementFragment.java b/app/src/main/java/com/afwsamples/testdpc/SetupManagementFragment.java
index 26c75481..462281a5 100644
--- a/app/src/main/java/com/afwsamples/testdpc/SetupManagementFragment.java
+++ b/app/src/main/java/com/afwsamples/testdpc/SetupManagementFragment.java
@@ -16,15 +16,6 @@
package com.afwsamples.testdpc;
-import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
-import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR;
-
import android.accounts.Account;
import android.annotation.TargetApi;
import android.app.Activity;
@@ -52,23 +43,34 @@
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
+
import com.afwsamples.testdpc.common.ColorPicker;
import com.afwsamples.testdpc.common.LaunchIntentUtil;
import com.afwsamples.testdpc.common.ProvisioningStateUtil;
import com.afwsamples.testdpc.common.Util;
-import com.android.setupwizardlib.SetupWizardLayout;
+import com.android.setupwizardlib.GlifLayout;
import com.android.setupwizardlib.view.NavigationBar;
+
import java.security.SecureRandom;
import java.util.Collections;
import java.util.Set;
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
+import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR;
+
/**
* This {@link Fragment} shows the UI that allows the user to start the setup of a managed profile
* or configuration of a device-owner if the device is in an appropriate state.
*/
public class SetupManagementFragment extends Fragment implements
- NavigationBar.NavigationBarListener, View.OnClickListener,
- ColorPicker.OnColorSelectListener, RadioGroup.OnCheckedChangeListener {
+ View.OnClickListener, ColorPicker.OnColorSelectListener,
+ RadioGroup.OnCheckedChangeListener {
// Tag for creating this fragment. This tag can be used to retrieve this fragment.
public static final String FRAGMENT_TAG = "SetupManagementFragment";
@@ -105,17 +107,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
mCurrentColor = savedInstanceState.getInt(EXTRA_PROVISIONING_MAIN_COLOR);
}
- // Use setupwizard theme
- final Context contextThemeWrapper =
- new ContextThemeWrapper(getActivity(), R.style.SetupTheme);
- LayoutInflater themeInflater = inflater.cloneInContext(contextThemeWrapper);
- View view = themeInflater.inflate(R.layout.setup_management_fragment, container, false);
- SetupWizardLayout layout = (SetupWizardLayout) view.findViewById(R.id.setup_wizard_layout);
- NavigationBar navigationBar = layout.getNavigationBar();
- navigationBar.setNavigationBarListener(this);
- navigationBar.getBackButton().setText(R.string.exit);
- mNavigationNextButton = navigationBar.getNextButton();
- mNavigationNextButton.setText(R.string.setup_label);
+ View view = inflater.inflate(R.layout.setup_management_fragment, container, false);
+ GlifLayout layout = view.findViewById(R.id.setup_wizard_layout);
+
+ mNavigationNextButton = layout.findViewById(R.id.setup_button);
+ mNavigationNextButton.setOnClickListener(this::onNavigateNext);
+ layout.findViewById(R.id.exit_button).setOnClickListener(this::onNavigateBack);
mSetupManagementMessage = (TextView) view.findViewById(R.id.setup_management_message_id);
mSetupOptions = (RadioGroup) view.findViewById(R.id.setup_options);
@@ -166,7 +163,6 @@ public void onSaveInstanceState(Bundle outState) {
public void onResume() {
super.onResume();
- getActivity().getActionBar().hide();
if (setProvisioningMethodsVisibility()) {
// The extra logo uri and color are supported only from N
if (BuildCompat.isAtLeastN()) {
@@ -468,13 +464,11 @@ public void onColorSelected(int colorValue, String id) {
updateColorUi();
}
- @Override
- public void onNavigateBack() {
+ public void onNavigateBack(View view) {
getActivity().onBackPressed();
}
- @Override
- public void onNavigateNext() {
+ public void onNavigateNext(View view) {
if (mSetupOptions.getCheckedRadioButtonId() == R.id.setup_managed_profile) {
maybeLaunchProvisioning(ACTION_PROVISION_MANAGED_PROFILE,
REQUEST_PROVISION_MANAGED_PROFILE);
diff --git a/app/src/main/java/com/afwsamples/testdpc/common/NotificationUtil.java b/app/src/main/java/com/afwsamples/testdpc/common/NotificationUtil.java
index 01a4934d..3bb6880e 100644
--- a/app/src/main/java/com/afwsamples/testdpc/common/NotificationUtil.java
+++ b/app/src/main/java/com/afwsamples/testdpc/common/NotificationUtil.java
@@ -56,6 +56,7 @@ private static void createDefaultNotificationChannel(Context context) {
String appName = context.getString(R.string.app_name);
NotificationChannel channel = new NotificationChannel(DEFAULT_CHANNEL_ID,
appName, NotificationManager.IMPORTANCE_DEFAULT);
+ channel.setImportance(NotificationManager.IMPORTANCE_LOW);
notificationManager.createNotificationChannel(channel);
}
diff --git a/app/src/main/java/com/afwsamples/testdpc/common/Util.java b/app/src/main/java/com/afwsamples/testdpc/common/Util.java
index cdb4660e..fe1c37dc 100644
--- a/app/src/main/java/com/afwsamples/testdpc/common/Util.java
+++ b/app/src/main/java/com/afwsamples/testdpc/common/Util.java
@@ -165,17 +165,12 @@ public static List getBindDeviceAdminTargetUsers(Context context) {
public static void showFileViewerForImportingCertificate(PreferenceFragment fragment,
int requestCode) {
- showFilePicker(fragment, "*/*", requestCode);
- }
-
- public static void showFilePicker(PreferenceFragment fragment, String type, int requestCode) {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setTypeAndNormalize(type);
+ Intent certIntent = new Intent(Intent.ACTION_GET_CONTENT);
+ certIntent.setTypeAndNormalize("*/*");
try {
- fragment.startActivityForResult(intent, requestCode);
+ fragment.startActivityForResult(certIntent, requestCode);
} catch (ActivityNotFoundException e) {
- Log.e(TAG, "showFilePicker: ", e);
+ Log.e(TAG, "showFileViewerForImportingCertificate: ", e);
}
}
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/MeteredDataRestrictionInfoAdapter.java b/app/src/main/java/com/afwsamples/testdpc/policy/MeteredDataRestrictionInfoAdapter.java
index 31239e0b..ff01464a 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/MeteredDataRestrictionInfoAdapter.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/MeteredDataRestrictionInfoAdapter.java
@@ -98,7 +98,7 @@ public void onClick(DialogInterface dialog, int which) {
@TargetApi(28)
private void setMeteredDataRestrictedPkgs(List pkgNames) {
- final List excludedPkgs = mDevicePolicyManager.setMeteredDataDisabled(
+ final List excludedPkgs = mDevicePolicyManager.setMeteredDataDisabledPackages(
DeviceAdminReceiver.getComponentName(mContext), pkgNames);
if (!excludedPkgs.isEmpty()) {
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/OverrideApnFragment.java b/app/src/main/java/com/afwsamples/testdpc/policy/OverrideApnFragment.java
index c8906735..e326669e 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/OverrideApnFragment.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/OverrideApnFragment.java
@@ -23,6 +23,7 @@
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
+import android.net.Uri;
import android.os.Bundle;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
@@ -30,16 +31,19 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
import android.widget.EditText;
+import android.widget.Spinner;
import android.widget.Toast;
+
import com.afwsamples.testdpc.DeviceAdminReceiver;
import com.afwsamples.testdpc.R;
import com.afwsamples.testdpc.common.BaseSearchablePolicyPreferenceFragment;
+
import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.net.UnknownHostException;
-import java.util.Arrays;
import java.util.List;
@TargetApi(28)
@@ -110,6 +114,27 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
return false;
}
+ void setUpSpinner(View dialogView, int viewId, int textArrayId) {
+ final Spinner spinner = (Spinner) dialogView.findViewById(viewId);
+ final ArrayAdapter adapter = ArrayAdapter.createFromResource(
+ getActivity(), textArrayId, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ }
+
+ void setUpAllSpinners(View dialogView) {
+ // Set up spinner for auth type.
+ setUpSpinner(dialogView, R.id.apn_auth_type, R.array.apn_auth_type_choices);
+ // Set up spinner for protocol.
+ setUpSpinner(dialogView, R.id.apn_protocol, R.array.apn_protocol_choices);
+ // Set up spinner for roaming protocol.
+ setUpSpinner(dialogView, R.id.apn_roaming_protocol, R.array.apn_protocol_choices);
+ // Set up spinner for mvno type.
+ setUpSpinner(dialogView, R.id.apn_mvno_type, R.array.apn_mvno_type_choices);
+ // Set up spinner for carrier enabled.
+ setUpSpinner(dialogView, R.id.apn_carrier_enabled, R.array.apn_carrier_enabled_choices);
+ }
+
void showInsertOverrideApnDialog() {
if (getActivity() == null || getActivity().isFinishing()) {
return;
@@ -135,26 +160,19 @@ void showInsertOverrideApnDialog() {
R.id.apn_user);
final EditText passwordEditText = (EditText) dialogView.findViewById(
R.id.apn_password);
- final EditText authTypeEditText = (EditText) dialogView.findViewById(
- R.id.apn_auth_type);
final EditText typeEditText = (EditText) dialogView.findViewById(
R.id.apn_type);
final EditText numericEditText = (EditText) dialogView.findViewById(
R.id.apn_numeric);
- final EditText protocolEditText = (EditText) dialogView.findViewById(
- R.id.apn_protocol);
- final EditText roamingProtocolEditText = (EditText) dialogView.findViewById(
- R.id.apn_roaming_protocol);
- final EditText carrierEnabledEditText = (EditText) dialogView.findViewById(
- R.id.apn_carrier_enabled);
final EditText networkBitmaskEditText = (EditText) dialogView.findViewById(
R.id.apn_network_bitmask);
- final EditText mvnoTypeEditText = (EditText) dialogView.findViewById(
- R.id.apn_mvno_type);
+ setUpAllSpinners(dialogView);
+
+ entryNameEditText.setHint(R.string.apn_entry_name_cannot_be_empty);
+ apnNameEditText.setHint(R.string.apn_name_cannot_be_empty);
+ typeEditText.setHint(R.string.apn_type_cannot_be_zero);
- authTypeEditText.setHint(R.string.apn_auth_type_hint);
numericEditText.setHint(R.string.apn_numeric_hint);
- carrierEnabledEditText.setHint(R.string.apn_carrier_enabled_hint);
new AlertDialog.Builder(getActivity())
.setTitle(R.string.insert_override_apn)
@@ -162,17 +180,19 @@ void showInsertOverrideApnDialog() {
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
final String entryName = entryNameEditText.getText().toString();
if (entryName.isEmpty()) {
- showToast(R.string.apn_no_entry_name);
+ showToast(R.string.apn_entry_name_cannot_be_empty);
return;
}
final String apnName = apnNameEditText.getText().toString();
if (apnName.isEmpty()) {
- showToast(R.string.apn_no_apn_name);
+ showToast(R.string.apn_name_cannot_be_empty);
+ return;
+ }
+ final int apnTypeBitmask = parseInt(typeEditText.getText().toString(), 0);
+ if (apnTypeBitmask == 0) {
+ showToast(R.string.apn_type_cannot_be_zero);
return;
}
- int authType = parseInt(authTypeEditText.getText().toString(), 0);
- int enabled = parseInt(carrierEnabledEditText.getText().toString(), 0);
- int networkbitmask = parseInt(networkBitmaskEditText.getText().toString(), 0);
ApnSetting apn = makeApnSetting(
numericEditText.getText().toString(),
@@ -180,18 +200,28 @@ void showInsertOverrideApnDialog() {
apnName,
inetAddressFromString(proxyEditText.getText().toString()),
parseInt(portEditText.getText().toString(), -1),
- URLFromString(mmscEditText.getText().toString()),
+ UriFromString(mmscEditText.getText().toString()),
inetAddressFromString(mmsProxyEditText.getText().toString()),
parseInt(mmsPortEditText.getText().toString(), -1),
userEditText.getText().toString(),
passwordEditText.getText().toString(),
- authType,
- Arrays.asList(parseTypes(typeEditText.getText().toString())),
- protocolEditText.getText().toString(),
- roamingProtocolEditText.getText().toString(),
- enabled == 1,
- networkbitmask,
- mvnoTypeEditText.getText().toString()
+ // -1 here as we have extra default choice "Not specified" in the
+ // spinner of auth type, protocol, roaming protocol and mvno type
+ // in case user doesn't want to specify these fields. And
+ // "Not Specified" should be transformed into "-1" in the builder
+ // of ApnSetting.
+ ((Spinner)dialogView.findViewById(R.id.apn_auth_type))
+ .getSelectedItemPosition() - 1,
+ apnTypeBitmask,
+ ((Spinner)dialogView.findViewById(R.id.apn_protocol))
+ .getSelectedItemPosition() - 1,
+ ((Spinner)dialogView.findViewById(
+ R.id.apn_roaming_protocol)).getSelectedItemPosition() - 1,
+ ((Spinner)dialogView.findViewById(
+ R.id.apn_carrier_enabled)).getSelectedItemPosition() == 1,
+ parseInt(networkBitmaskEditText.getText().toString(), 0),
+ ((Spinner)dialogView.findViewById(R.id.apn_mvno_type))
+ .getSelectedItemPosition() - 1
);
int insertedId = mDevicePolicyManager.addOverrideApn(mAdminComponentName, apn);
if (insertedId == -1) {
@@ -221,23 +251,23 @@ private int parseInt(String str, int defaultValue) {
}
private ApnSetting makeApnSetting(String operatorNumeric, String entryName, String apnName,
- InetAddress proxy, int port, URL mmsc, InetAddress mmsProxy, int mmsPort,
- String user, String password, int authType, List types, String protocol,
- String roamingProtocol, boolean carrierEnabled, int networkTypeBitmask,
- String mvnoType) {
- ApnSetting.Builder builder = new ApnSetting.Builder();
- return builder.setOperatorNumeric(operatorNumeric)
+ InetAddress proxyAddress, int proxyPort, Uri mmsc, InetAddress mmsProxyAddress,
+ int mmsProxyPort, String user, String password, int authType, int apnTypeBitmask,
+ int protocol, int roamingProtocol, boolean carrierEnabled, int networkTypeBitmask,
+ int mvnoType) {
+ return new ApnSetting.Builder()
+ .setOperatorNumeric(operatorNumeric)
.setEntryName(entryName)
.setApnName(apnName)
- .setProxy(proxy)
- .setPort(port)
+ .setProxyAddress(proxyAddress)
+ .setProxyPort(proxyPort)
.setMmsc(mmsc)
- .setMmsProxy(mmsProxy)
- .setMmsPort(mmsPort)
+ .setMmsProxyAddress(mmsProxyAddress)
+ .setMmsProxyPort(mmsProxyPort)
.setUser(user)
.setPassword(password)
.setAuthType(authType)
- .setTypes(types)
+ .setApnTypeBitmask(apnTypeBitmask)
.setProtocol(protocol)
.setRoamingProtocol(roamingProtocol)
.setCarrierEnabled(carrierEnabled)
@@ -246,14 +276,8 @@ private ApnSetting makeApnSetting(String operatorNumeric, String entryName, Stri
.build();
}
- private URL URLFromString(String url) {
- try {
- return TextUtils.isEmpty(url) ? null : new URL(url);
- } catch (MalformedURLException e) {
- Log.e(LOG_TAG, "Can't parse URL from string.");
- showToast(R.string.apn_wrong_url);
- return null;
- }
+ private Uri UriFromString(String uri) {
+ return TextUtils.isEmpty(uri) ? null : Uri.parse(uri);
}
private InetAddress inetAddressFromString(String inetAddress) {
@@ -269,18 +293,6 @@ private InetAddress inetAddressFromString(String inetAddress) {
}
}
- private String[] parseTypes(String types) {
- String[] result;
- // If unset, set to DEFAULT.
- if (TextUtils.isEmpty(types)) {
- result = new String[1];
- result[0] = "*";
- } else {
- result = types.split(",");
- }
- return result;
- }
-
private void reloadEnableOverrideApnUi() {
boolean enabled = mDevicePolicyManager.isOverrideApnEnabled(mAdminComponentName);
if (mEnableOverrideApnPreference.isEnabled()) {
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/PolicyManagementFragment.java b/app/src/main/java/com/afwsamples/testdpc/policy/PolicyManagementFragment.java
index 08efa0d5..dea10075 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/PolicyManagementFragment.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/PolicyManagementFragment.java
@@ -52,7 +52,6 @@
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.service.notification.NotificationListenerService;
-import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.annotation.StringRes;
import android.support.v14.preference.SwitchPreference;
@@ -119,7 +118,6 @@
import com.afwsamples.testdpc.profilepolicy.apprestrictions.ManageAppRestrictionsFragment;
import com.afwsamples.testdpc.profilepolicy.delegation.DelegationFragment;
import com.afwsamples.testdpc.profilepolicy.permission.ManageAppPermissionsFragment;
-import com.afwsamples.testdpc.safetynet.SafetyNetFragment;
import com.afwsamples.testdpc.transferownership.PickTransferComponentFragment;
import com.afwsamples.testdpc.util.MainThreadExecutor;
@@ -284,13 +282,6 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
private static final String MANAGE_APP_RESTRICTIONS_KEY = "manage_app_restrictions";
private static final String MANAGED_PROFILE_SPECIFIC_POLICIES_KEY = "managed_profile_policies";
private static final String MANAGE_LOCK_TASK_LIST_KEY = "manage_lock_task";
- private static final String MANDATORY_BACKUPS = "mandatory_backups";
- private static final String MANDATORY_BACKUP_ACCOUNT_CHANGED_ACTION =
- "com.google.android.gms.backup.MANDATORY_BACKUP_ACCOUNT_CHANGED";
- private static final String MANDATORY_BACKUP_ACCOUNT_NAME_APP_RESTRICTION =
- "mandatoryBackupAccountName";
- private static final String MANDATORY_BACKUP_ACCOUNT_TYPE_APP_RESTRICTION =
- "mandatoryBackupAccountType";
private static final String MUTE_AUDIO_KEY = "mute_audio";
private static final String NETWORK_STATS_KEY = "network_stats";
private static final String PASSWORD_CONSTRAINTS_KEY = "password_constraints";
@@ -356,7 +347,6 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
private static final String TAG_WIFI_CONFIG_CREATION = "wifi_config_creation";
private static final String WIFI_CONFIG_LOCKDOWN_ON = "1";
private static final String WIFI_CONFIG_LOCKDOWN_OFF = "0";
- private static final String SAFETYNET_ATTEST = "safetynet_attest";
private static final String SECURITY_PATCH_FORMAT = "yyyy-MM-dd";
private static final String SET_NEW_PASSWORD = "set_new_password";
private static final String SET_PROFILE_PARENT_NEW_PASSWORD = "set_profile_parent_new_password";
@@ -377,9 +367,6 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
BatteryManager.BATTERY_PLUGGED_USB |
BatteryManager.BATTERY_PLUGGED_WIRELESS);
private static final String DONT_STAY_ON = "0";
- public static final String GMSCORE_PACKAGE = "com.google.android.gms";
- public static final String GMSCORE_BACKUP_TRANSPORT =
- "com.google.android.gms.backup.BackupTransportService";
private static final int USER_OPERATION_ERROR_UNKNOWN = 1;
private static final int USER_OPERATION_SUCCESS = 0;
@@ -407,7 +394,6 @@ public class PolicyManagementFragment extends BaseSearchablePolicyPreferenceFrag
private DpcSwitchPreference mInstallNonMarketAppsPreference;
private SwitchPreference mEnableBackupServicePreference;
- private SwitchPreference mMandatoryBackupsPreference;
private SwitchPreference mEnableSecurityLoggingPreference;
private SwitchPreference mEnableNetworkLoggingPreference;
private SwitchPreference mSetAutoTimeRequiredPreference;
@@ -525,8 +511,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
findPreference(REMOVE_DEVICE_OWNER_KEY).setOnPreferenceClickListener(this);
mEnableBackupServicePreference = (SwitchPreference) findPreference(ENABLE_BACKUP_SERVICE);
mEnableBackupServicePreference.setOnPreferenceChangeListener(this);
- mMandatoryBackupsPreference = (SwitchPreference) findPreference(MANDATORY_BACKUPS);
- mMandatoryBackupsPreference.setOnPreferenceChangeListener(this);
findPreference(REQUEST_BUGREPORT_KEY).setOnPreferenceClickListener(this);
mEnableSecurityLoggingPreference =
(SwitchPreference) findPreference(ENABLE_SECURITY_LOGGING);
@@ -599,7 +583,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
findPreference(REBOOT_KEY).setOnPreferenceClickListener(this);
findPreference(SET_SHORT_SUPPORT_MESSAGE_KEY).setOnPreferenceClickListener(this);
findPreference(SET_LONG_SUPPORT_MESSAGE_KEY).setOnPreferenceClickListener(this);
- findPreference(SAFETYNET_ATTEST).setOnPreferenceClickListener(this);
findPreference(SET_NEW_PASSWORD).setOnPreferenceClickListener(this);
findPreference(SET_PROFILE_PARENT_NEW_PASSWORD).setOnPreferenceClickListener(this);
findPreference(CROSS_PROFILE_APPS).setOnPreferenceClickListener(this);
@@ -640,7 +623,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
reloadScreenCaptureDisableUi();
reloadMuteAudioUi();
reloadEnableBackupServiceUi();
- reloadMandatoryBackupsUi();
reloadEnableSecurityLoggingUi();
reloadEnableNetworkLoggingUi();
reloadSetAutoTimeRequiredUi();
@@ -996,10 +978,6 @@ public void onPositiveButtonClicked(String[] lockTaskArray) {
showFragment(SetSupportMessageFragment.newInstance(
SetSupportMessageFragment.TYPE_LONG));
return true;
- case SAFETYNET_ATTEST:
- DialogFragment safetynetFragment = new SafetyNetFragment();
- safetynetFragment.show(getFragmentManager(), SafetyNetFragment.class.getName());
- return true;
case SET_NEW_PASSWORD:
startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
return true;
@@ -1144,16 +1122,7 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
case ENABLE_BACKUP_SERVICE:
setBackupServiceEnabled((Boolean) newValue);
reloadEnableBackupServiceUi();
- reloadMandatoryBackupsUi();
return true;
- case MANDATORY_BACKUPS:
- if ((Boolean) newValue) {
- showMandatoryBackupAccountPicker();
- return false;
- } else {
- setupMandatoryBackups(null);
- return true;
- }
case ENABLE_SECURITY_LOGGING:
setSecurityLoggingEnabled((Boolean) newValue);
reloadEnableSecurityLoggingUi();
@@ -1281,8 +1250,8 @@ private boolean installKeyPair(final PrivateKey key, final Certificate cert, fin
boolean isUserSelectable) {
if (BuildCompat.isAtLeastP()) {
return mDevicePolicyManager.installKeyPair(
- mAdminComponentName, key, new Certificate[]{cert}, alias, false,
- isUserSelectable);
+ mAdminComponentName, key, new Certificate[]{cert}, alias,
+ isUserSelectable ? DevicePolicyManager.INSTALLKEY_SET_USER_SELECTABLE : 0);
} else {
if (!isUserSelectable) {
throw new IllegalArgumentException(
@@ -2097,14 +2066,6 @@ private void reloadEnableBackupServiceUi() {
}
}
- @TargetApi(28)
- private void reloadMandatoryBackupsUi() {
- if (mMandatoryBackupsPreference.isEnabled()) {
- mMandatoryBackupsPreference.setChecked(
- null != mDevicePolicyManager.getMandatoryBackupTransport());
- }
- }
-
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void reloadScreenCaptureDisableUi() {
boolean isScreenCaptureDisabled = mDevicePolicyManager.getScreenCaptureDisabled(
@@ -2790,7 +2751,7 @@ private void showSetMeteredDataPrompt() {
@TargetApi(28)
private List getMeteredDataRestrictedPkgs() {
- return mDevicePolicyManager.getMeteredDataDisabled(mAdminComponentName);
+ return mDevicePolicyManager.getMeteredDataDisabledPackages(mAdminComponentName);
}
/**
@@ -3118,7 +3079,7 @@ private void relaunchInLockTaskMode() {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLockTaskMode(true);
+ options.setLockTaskEnabled(true);
try {
startActivity(intent, options.toBundle());
@@ -3389,65 +3350,6 @@ private int validateAffiliatedUserAfterP() {
}
}
- @TargetApi(28)
- private void showMandatoryBackupAccountPicker() {
- if (!BuildCompat.isAtLeastP()) {
- return;
- }
- if (getActivity() == null || getActivity().isFinishing()) {
- return;
- }
- List accounts = Arrays.asList(mAccountManager.getAccounts());
- if (accounts.isEmpty()) {
- showToast(R.string.no_accounts_available);
- } else {
- AccountArrayAdapter accountArrayAdapter =
- new AccountArrayAdapter(getActivity(), R.id.account_name, accounts);
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.mandatory_backup_account)
- .setAdapter(
- accountArrayAdapter,
- (dialog, position) -> setupMandatoryBackups(accounts.get(position)))
- .show();
- }
- }
-
- @TargetApi(28)
- private void setupMandatoryBackups(@Nullable Account account) {
- boolean makeBackupsMandatory = account != null;
- // For the data to be backed up to Google Drive, set the backup transport to the GmsCore's
- // backup transport.
- mDevicePolicyManager.setMandatoryBackupTransport(mAdminComponentName, makeBackupsMandatory ?
- new ComponentName(GMSCORE_PACKAGE, GMSCORE_BACKUP_TRANSPORT) : null);
-
- // Set app restrictions with the account type and name on GmsCore to let it know which
- // account it should use for backing up the data and notify GmsCore about the change by
- // sending a broadcast to it.
- String name = account != null ? account.name : null;
- String type = account != null ? account.type: null;
- Bundle appRestrictions = mDevicePolicyManager.getApplicationRestrictions(
- mAdminComponentName, GMSCORE_PACKAGE);
- if (name == null) {
- appRestrictions.remove(MANDATORY_BACKUP_ACCOUNT_NAME_APP_RESTRICTION);
- } else {
- appRestrictions.putString(MANDATORY_BACKUP_ACCOUNT_NAME_APP_RESTRICTION, name);
- }
- if (type == null) {
- appRestrictions.remove(MANDATORY_BACKUP_ACCOUNT_TYPE_APP_RESTRICTION);
- } else {
- appRestrictions.putString(MANDATORY_BACKUP_ACCOUNT_TYPE_APP_RESTRICTION, type);
- }
- mDevicePolicyManager.setApplicationRestrictions(
- mAdminComponentName, GMSCORE_PACKAGE, appRestrictions);
- Intent intent = new Intent(MANDATORY_BACKUP_ACCOUNT_CHANGED_ACTION);
- intent.setPackage(GMSCORE_PACKAGE);
- getContext().sendBroadcast(intent);
-
- // Update the UI for backup-related policies.
- reloadEnableBackupServiceUi();
- reloadMandatoryBackupsUi();
- }
-
abstract class ManageLockTaskListCallback {
public abstract void onPositiveButtonClicked(String[] lockTaskArray);
}
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordBlacklistFragment.java b/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordBlacklistFragment.java
deleted file mode 100644
index d90710e8..00000000
--- a/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordBlacklistFragment.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.afwsamples.testdpc.policy.keyguard;
-
-import android.annotation.TargetApi;
-import android.app.AlertDialog;
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.annotation.StringRes;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.EditText;
-import android.widget.SpinnerAdapter;
-import android.widget.Toast;
-import com.afwsamples.testdpc.DeviceAdminReceiver;
-import com.afwsamples.testdpc.R;
-import com.afwsamples.testdpc.common.BaseManageComponentFragment;
-import com.afwsamples.testdpc.common.EditDeleteArrayAdapter;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-@TargetApi(28)
-public class PasswordBlacklistFragment extends BaseManageComponentFragment
- implements EditDeleteArrayAdapter.OnEditButtonClickListener {
-
- public PasswordConstraintsFragment passwordConstraintsFragment;
-
- private List mPasswordBlacklist = new ArrayList<>();
- private DevicePolicyManager mDevicePolicyManager;
- private ComponentName mAdminComponent;
- private EditDeleteArrayAdapter mPasswordBlacklistArrayAdapter;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mAdminComponent = DeviceAdminReceiver.getComponentName(getActivity());
- }
-
- public void setDpm(DevicePolicyManager dpm) {
- mDevicePolicyManager = dpm;
- }
-
- @Override
- public View onCreateView(LayoutInflater layoutInflater, ViewGroup container,
- Bundle savedInstanceState) {
- View view = super.onCreateView(layoutInflater, container, savedInstanceState);
- mManagedAppsSpinner.setVisibility(View.INVISIBLE); // We don't need the Spinner.
- return view;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- getActivity().getActionBar().setTitle(R.string.password_blacklist_manager_title);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- if (passwordConstraintsFragment != null) {
- // Blacklist has changed so updated the preferences
- // TODO: there must be a neater way to do this but onResume isn't called on navigation
- passwordConstraintsFragment.refreshBlacklistPreferences();
- }
- }
-
- @Override
- protected SpinnerAdapter createSpinnerAdapter() {
- return null; // We don't need a spinner.
- }
-
- @Override
- protected void onSpinnerItemSelected(Void item) {
- }
-
- @Override
- protected BaseAdapter createListAdapter() {
- mPasswordBlacklistArrayAdapter = new PasswordBlacklistEntryArrayAdapter(
- getActivity(), mPasswordBlacklist, this);
- return mPasswordBlacklistArrayAdapter;
- }
-
- @Override
- protected void resetConfig() {
- mPasswordBlacklistArrayAdapter.clear();
- }
-
- @Override
- protected void saveConfig() {
- // Name the blacklist with the timestamp when it was set
- final String name = DateFormat.getDateTimeInstance().format(new Date());
- if (!setBlacklist(mDevicePolicyManager, mAdminComponent, name, mPasswordBlacklist)) {
- showToast(R.string.password_blacklist_save_failed);
- return;
- }
-
- showToast(R.string.password_blacklist_saved);
- }
-
- @Override
- protected void addNewRow() {
- onEditButtonClick(null);
- }
-
- @Override
- protected void loadDefault() {
- mPasswordBlacklistArrayAdapter.clear();
- }
-
- @Override
- public void onEditButtonClick(final String existingEntry) {
- View view = LayoutInflater.from(getActivity()).inflate(R.layout.simple_edittext, null);
- final EditText input = view.findViewById(R.id.input);
- if (existingEntry != null) {
- input.setText(existingEntry);
- }
-
- final AlertDialog dialog = new AlertDialog.Builder(getActivity())
- .setTitle(R.string.password_blacklist_add)
- .setView(view)
- .setPositiveButton(android.R.string.ok, null)
- .setNegativeButton(android.R.string.cancel, null)
- .create();
- dialog.setOnShowListener(
- dialogInterface -> dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(
- okButtonView -> {
- String password = input.getText().toString();
- if (TextUtils.isEmpty(password)) {
- showToast(R.string.password_blacklist_add_empty_error);
- return;
- }
- if (existingEntry != null) {
- mPasswordBlacklistArrayAdapter.remove(existingEntry);
- }
- mPasswordBlacklistArrayAdapter.add(password);
- dialog.dismiss();
- }));
- dialog.show();
- }
-
- private void showToast(@StringRes int stringResId) {
- Toast.makeText(getActivity(), stringResId, Toast.LENGTH_LONG).show();
- }
-
- static class PasswordBlacklistEntryArrayAdapter extends EditDeleteArrayAdapter {
- PasswordBlacklistEntryArrayAdapter(
- Context context,
- List entries,
- OnEditButtonClickListener onEditButtonClickListener) {
- super(context, entries, onEditButtonClickListener, null);
- }
-
- @Override
- protected String getDisplayName(String entry) {
- return entry;
- }
- }
-
- @TargetApi(28)
- static boolean setBlacklist(DevicePolicyManager dpm, ComponentName admin, String name,
- List blacklist) {
- return dpm.setPasswordBlacklist(admin, name, blacklist);
- }
-
- @TargetApi(28)
- static String getBlacklistName(DevicePolicyManager dpm, ComponentName admin) {
- return dpm.getPasswordBlacklistName(admin);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordConstraintsFragment.java b/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordConstraintsFragment.java
index b1174ceb..96ec8292 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordConstraintsFragment.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/keyguard/PasswordConstraintsFragment.java
@@ -16,15 +16,20 @@
package com.afwsamples.testdpc.policy.keyguard;
-import android.app.Activity;
-import android.app.Fragment;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+import static com.afwsamples.testdpc.common.preference.DpcPreferenceHelper.NO_CUSTOM_CONSTRIANT;
+
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
-import android.support.v4.os.BuildCompat;
import android.support.v7.preference.EditTextPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
@@ -35,29 +40,14 @@
import com.afwsamples.testdpc.common.ProfileOrParentFragment;
import com.afwsamples.testdpc.common.Util;
import com.afwsamples.testdpc.common.preference.CustomConstraint;
-import com.afwsamples.testdpc.common.preference.DpcPreference;
import com.afwsamples.testdpc.common.preference.DpcPreferenceBase;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.text.DateFormat;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-import static com.afwsamples.testdpc.common.preference.DpcPreferenceHelper.NO_CUSTOM_CONSTRIANT;
-
/**
* This fragment provides functionalities to set password constraint policies as a profile
* or device owner. In the former case, it is also possible to set password constraints on
@@ -74,12 +64,10 @@
* {@link DevicePolicyManager#setPasswordMinimumSymbols(ComponentName, int)}
* {@link DevicePolicyManager#setPasswordMinimumNonLetter(ComponentName, int)}
* {@link DevicePolicyManager#setPasswordHistoryLength(ComponentName, int)}
- * {@link DevicePolicyManager#setPasswordBlacklist(ComponentName, String, List)}
*
*/
public final class PasswordConstraintsFragment extends ProfileOrParentFragment implements
- Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
- private static final int READ_BLACKLIST_FILE_CODE = 42;
+ Preference.OnPreferenceChangeListener {
private DpcPreferenceBase mMinLength;
private DpcPreferenceBase mMinLetters;
@@ -88,7 +76,6 @@ public final class PasswordConstraintsFragment extends ProfileOrParentFragment i
private DpcPreferenceBase mMinUpper;
private DpcPreferenceBase mMinSymbols;
private DpcPreferenceBase mMinNonLetter;
- private DpcPreference mClearBlacklist;
public static class Container extends ProfileOrParentFragment.Container {
@Override
@@ -111,10 +98,6 @@ abstract static class Keys {
final static String MIN_UPPERCASE = "password_min_uppercase";
final static String MIN_SYMBOLS = "password_min_symbols";
final static String MIN_NONLETTER = "password_min_nonletter";
-
- final static String SET_PASSWORD_BLACKLIST_KEY = "set_password_blacklist";
- final static String LOAD_PASSWORD_BLACKLIST_KEY = "load_password_blacklist";
- final static String CLEAR_PASSWORD_BLACKLIST_KEY = "clear_password_blacklist";
}
private static final TreeMap PASSWORD_QUALITIES = new TreeMap<>();
@@ -169,7 +152,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
mMinUpper = (DpcPreferenceBase) findPreference(Keys.MIN_UPPERCASE);
mMinSymbols = (DpcPreferenceBase) findPreference(Keys.MIN_SYMBOLS);
mMinNonLetter = (DpcPreferenceBase) findPreference(Keys.MIN_NONLETTER);
- mClearBlacklist = (DpcPreference) findPreference(Keys.CLEAR_PASSWORD_BLACKLIST_KEY);
// Populate password quality settings - messy because the only API for this requires two
// separate String[]s.
@@ -199,10 +181,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setup(Keys.MIN_SYMBOLS, getDpm().getPasswordMinimumSymbols(getAdmin()));
setup(Keys.MIN_NONLETTER, getDpm().getPasswordMinimumNonLetter(getAdmin()));
- findPreference(Keys.SET_PASSWORD_BLACKLIST_KEY).setOnPreferenceClickListener(this);
- findPreference(Keys.LOAD_PASSWORD_BLACKLIST_KEY).setOnPreferenceClickListener(this);
- mClearBlacklist.setOnPreferenceClickListener(this);
-
setPreferencesConstraint();
}
@@ -212,9 +190,6 @@ public void onResume() {
// Settings that may have been changed by other users need updating.
updateExpirationTimes();
- if (BuildCompat.isAtLeastP()) {
- refreshBlacklistPreferences();
- }
}
@Override
@@ -282,43 +257,6 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
- public boolean onPreferenceClick(Preference preference) {
- String key = preference.getKey();
- switch (key) {
- case Keys.SET_PASSWORD_BLACKLIST_KEY:
- showPasswordBlacklistFragment();
- return true;
- case Keys.LOAD_PASSWORD_BLACKLIST_KEY:
- Util.showFilePicker(this, "text/plain", READ_BLACKLIST_FILE_CODE);
- return true;
- case Keys.CLEAR_PASSWORD_BLACKLIST_KEY:
- PasswordBlacklistFragment.setBlacklist(getDpm(), getAdmin(), null, null);
- refreshBlacklistPreferences();
- return true;
- default:
- break;
- }
-
- return false;
- }
-
- private void showPasswordBlacklistFragment() {
- final PasswordBlacklistFragment fragment = new PasswordBlacklistFragment();
-
- fragment.passwordConstraintsFragment = this;
- fragment.setDpm(getDpm());
-
- Fragment containerFragment = getParentFragment();
- if (containerFragment == null) {
- containerFragment = this;
- }
- containerFragment.getFragmentManager().beginTransaction()
- .addToBackStack(PasswordBlacklistFragment.class.getName())
- .hide(containerFragment)
- .add(R.id.container, fragment)
- .commit();
- }
-
/**
* Enable and disable password constraint preferences based on the current password quality.
*/
@@ -340,10 +278,6 @@ private void setPreferencesConstraint() {
mMinUpper.setCustomConstraint(constraint);
mMinSymbols.setCustomConstraint(constraint);
mMinNonLetter.setCustomConstraint(constraint);
-
- mClearBlacklist.setCustomConstraint(
- () -> PasswordBlacklistFragment.getBlacklistName(getDpm(), getAdmin()) != null
- ? NO_CUSTOM_CONSTRIANT : R.string.password_blacklist_no_blacklist);
}
private void refreshPreferences() {
@@ -356,10 +290,6 @@ private void refreshPreferences() {
mMinNonLetter.refreshEnabledState();
}
- void refreshBlacklistPreferences() {
- mClearBlacklist.refreshEnabledState();
- mClearBlacklist.setSummary(PasswordBlacklistFragment.getBlacklistName(getDpm(), getAdmin()));
- }
/**
* Set an initial value. Updates the summary to match.
@@ -396,39 +326,4 @@ private void updateExpirationTimes() {
byAdmin.setSummary(Util.formatTimestamp(getDpm().getPasswordExpiration(getAdmin())));
byAll.setSummary(Util.formatTimestamp(getDpm().getPasswordExpiration(null)));
}
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
- if (requestCode == READ_BLACKLIST_FILE_CODE && resultCode == Activity.RESULT_OK) {
- if (resultData != null) {
- final Uri uri = resultData.getData();
- final List blacklist;
- try {
- blacklist = readTextFileLines(uri);
- } catch (IOException e) {
- Toast.makeText(getActivity(), R.string.password_blacklist_load_failed,
- Toast.LENGTH_LONG).show();
- return;
- }
- final String name = DateFormat.getDateTimeInstance().format(new Date());
- if (!PasswordBlacklistFragment.setBlacklist(getDpm(), getAdmin(), name,
- blacklist)) {
- Toast.makeText(getActivity(), R.string.password_blacklist_save_failed,
- Toast.LENGTH_LONG).show();
- }
- }
- }
- }
-
- private List readTextFileLines(Uri uri) throws IOException {
- final List lines = new ArrayList<>();
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(
- getActivity().getApplicationContext().getContentResolver().openInputStream(uri)))) {
- String line;
- while ((line = reader.readLine()) != null) {
- lines.add(line);
- }
- }
- return lines;
- }
}
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/locktask/SetLockTaskFeaturesFragment.java b/app/src/main/java/com/afwsamples/testdpc/policy/locktask/SetLockTaskFeaturesFragment.java
index 7f31381c..5d6684e6 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/locktask/SetLockTaskFeaturesFragment.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/locktask/SetLockTaskFeaturesFragment.java
@@ -20,6 +20,7 @@
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
import android.annotation.TargetApi;
@@ -60,18 +61,6 @@ public class SetLockTaskFeaturesFragment
private static final String KEY_GLOBAL_ACTIONS = "lock_task_feature_global_actions";
private static final String KEY_KEYGUARD = "lock_task_feature_keyguard";
- private static final int LOCK_TASK_FEATURE_OVERVIEW;
- static {
- int flag = 1 << 3;
- try {
- flag = ReflectionUtil.intConstant(
- DevicePolicyManager.class, "LOCK_TASK_FEATURE_OVERVIEW");
- } catch (ReflectionUtil.ReflectionIsTemporaryException e) {
- } finally {
- LOCK_TASK_FEATURE_OVERVIEW = flag;
- }
- }
-
/** Maps from preference keys to {@link DevicePolicyManager#setLockTaskFeatures}'s flags. */
private static final ArrayMap FEATURE_FLAGS = new ArrayMap<>();
static {
@@ -129,8 +118,8 @@ public boolean onPreferenceChange(Preference pref, Object val) {
? flagsBefore | FEATURE_FLAGS.get(key)
: flagsBefore & ~FEATURE_FLAGS.get(key);
if ((flagsAfter & LOCK_TASK_FEATURE_HOME) == 0) {
- // Disable OVERVIEW when HOME is disabled
- flagsAfter &= ~LOCK_TASK_FEATURE_OVERVIEW;
+ // Disable OVERVIEW and NOTIFICATION when HOME is disabled
+ flagsAfter &= ~(LOCK_TASK_FEATURE_OVERVIEW | LOCK_TASK_FEATURE_NOTIFICATIONS);
}
if (flagsAfter != flagsBefore) {
Log.i(TAG, "LockTask feature flags changing from 0x" + Integer.toHexString(flagsBefore)
@@ -155,8 +144,13 @@ public boolean isAvailable(Context context) {
}
private void enforceEnablingRestrictions(int enabledFeatures) {
- DpcSwitchPreference pref = (DpcSwitchPreference) findPreference(KEY_OVERVIEW);
- pref.setEnabled((enabledFeatures & LOCK_TASK_FEATURE_HOME) != 0);
+ boolean isHomeEnabled = (enabledFeatures & LOCK_TASK_FEATURE_HOME) != 0;
+ setPrefEnabledState((DpcSwitchPreference) findPreference(KEY_OVERVIEW), isHomeEnabled);
+ setPrefEnabledState((DpcSwitchPreference) findPreference(KEY_NOTIFICATIONS), isHomeEnabled);
+ }
+
+ private void setPrefEnabledState(DpcSwitchPreference pref, boolean enabled) {
+ pref.setEnabled(enabled);
if (!pref.isEnabled() && pref.isChecked()) {
pref.setChecked(false);
}
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/systemupdatepolicy/SystemUpdatePolicyFragment.java b/app/src/main/java/com/afwsamples/testdpc/policy/systemupdatepolicy/SystemUpdatePolicyFragment.java
index 275782e9..2a3b8038 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/systemupdatepolicy/SystemUpdatePolicyFragment.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/systemupdatepolicy/SystemUpdatePolicyFragment.java
@@ -21,6 +21,7 @@
import android.app.Fragment;
import android.app.TimePickerDialog;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.FreezePeriod;
import android.app.admin.SystemUpdatePolicy;
import android.content.Context;
import android.os.Build;
@@ -43,6 +44,7 @@
import com.afwsamples.testdpc.R;
import java.time.LocalDate;
+import java.time.MonthDay;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@@ -62,18 +64,20 @@ public class SystemUpdatePolicyFragment extends Fragment implements View.OnClick
@RequiresApi(api = Build.VERSION_CODES.O)
static class Period {
- LocalDate mStart;
- LocalDate mEnd;
+ MonthDay mStart;
+ MonthDay mEnd;
- public Period(Integer start, Integer end) {
- int currentYear = LocalDate.now().getYear();
- mStart = LocalDate.ofYearDay(2001, start).withYear(currentYear);
- mEnd = LocalDate.ofYearDay(2001, end).withYear(end >= start ? currentYear : currentYear + 1);
+ public Period() {
}
- public Period(LocalDate startDate, LocalDate endDate) {
- mStart = startDate;
- mEnd = endDate;
+ public Period(MonthDay start, MonthDay end) {
+ mStart = start;
+ mEnd = end;
+ }
+
+ public void set(LocalDate startDate, LocalDate endDate) {
+ mStart = MonthDay.of(startDate.getMonth(), startDate.getDayOfMonth());
+ mEnd = MonthDay.of(endDate.getMonth(), endDate.getDayOfMonth());
}
@Override
@@ -82,9 +86,17 @@ public String toString() {
return mStart.format(formatter) + " - " + mEnd.format(formatter);
}
- public Pair toIntegers() {
- return new Pair<>(mStart.withYear(2001).getDayOfYear(),
- mEnd.withYear(2001).getDayOfYear());
+ public LocalDate getStartDate() {
+ return mStart.atYear(LocalDate.now().getYear());
+ }
+
+ public LocalDate getEndDate() {
+ return mEnd.atYear(LocalDate.now().getYear());
+ }
+
+ @TargetApi(28)
+ public FreezePeriod toFreezePeriod() {
+ return new FreezePeriod(mStart, mEnd);
}
}
@@ -131,10 +143,9 @@ public View getView(int position, View convertView, ViewGroup parent) {
textView.setOnClickListener(view -> {
final Period period = (Period) view.getTag();
promptToSetFreezePeriod((LocalDate startDate, LocalDate endDate) -> {
- period.mStart = startDate;
- period.mEnd = endDate;
+ period.set(startDate, endDate);
mFreezePeriodAdapter.notifyDataSetChanged();
- }, period.mStart, period.mEnd);
+ }, period.getStartDate(), period.getEndDate());
});
View deleteButton = convertView.findViewById(R.id.delete_period);
deleteButton.setTag(mData.get(position));
@@ -210,7 +221,8 @@ public void onClick(View v) {
break;
case R.id.system_update_policy_btn_add_period:
promptToSetFreezePeriod((LocalDate startDate, LocalDate endDate) -> {
- Period period = new Period(startDate, endDate);
+ Period period = new Period();
+ period.set(startDate, endDate);
mFreezePeriods.add(period);
mFreezePeriodAdapter.notifyDataSetChanged();
}, LocalDate.now(), LocalDate.now());
@@ -269,21 +281,22 @@ private boolean setSystemUpdatePolicy() {
default:
newPolicy = null;
}
- if (BuildCompat.isAtLeastP() && newPolicy != null && mFreezePeriods.size() != 0) {
- List> periods = new ArrayList<>(mFreezePeriods.size());
- for (Period p : mFreezePeriods) {
- periods.add(p.toIntegers());
- }
- try {
+
+ try {
+ if (BuildCompat.isAtLeastP() && newPolicy != null && mFreezePeriods.size() != 0) {
+ final List periods = new ArrayList<>(mFreezePeriods.size());
+ for (Period p : mFreezePeriods) {
+ periods.add(p.toFreezePeriod());
+ }
newPolicy.setFreezePeriods(periods);
- mDpm.setSystemUpdatePolicy(DeviceAdminReceiver.getComponentName(getActivity()),
- newPolicy);
- Toast.makeText(getContext(), "Policy set successfully", Toast.LENGTH_LONG).show();
- return true;
- } catch (IllegalArgumentException e) {
- Toast.makeText(getContext(), "Failed to set system update policy: " + e.getMessage(),
- Toast.LENGTH_LONG).show();
}
+ mDpm.setSystemUpdatePolicy(DeviceAdminReceiver.getComponentName(getActivity()),
+ newPolicy);
+ Toast.makeText(getContext(), "Policy set successfully", Toast.LENGTH_LONG).show();
+ return true;
+ } catch (IllegalArgumentException e) {
+ Toast.makeText(getContext(), "Failed to set system update policy: " + e.getMessage(),
+ Toast.LENGTH_LONG).show();
}
return false;
}
@@ -332,10 +345,10 @@ private void reloadSystemUpdatePolicy() {
break;
}
if (BuildCompat.isAtLeastP()) {
- List> freezePeriods = policy.getFreezePeriods();
+ List freezePeriods = policy.getFreezePeriods();
mFreezePeriods.clear();
- for (Pair period : freezePeriods) {
- Period p = new Period(period.first, period.second);
+ for (FreezePeriod period : freezePeriods) {
+ Period p = new Period(period.getStart(), period.getEnd());
mFreezePeriods.add(p);
}
mFreezePeriodAdapter.notifyDataSetChanged();
diff --git a/app/src/main/java/com/afwsamples/testdpc/policy/wifimanagement/WifiConfigCreationDialog.java b/app/src/main/java/com/afwsamples/testdpc/policy/wifimanagement/WifiConfigCreationDialog.java
index 372fee15..161f97fd 100644
--- a/app/src/main/java/com/afwsamples/testdpc/policy/wifimanagement/WifiConfigCreationDialog.java
+++ b/app/src/main/java/com/afwsamples/testdpc/policy/wifimanagement/WifiConfigCreationDialog.java
@@ -149,7 +149,6 @@ public void onDismiss(DialogInterface dialog) {
if (mListener != null) {
mListener.onDismiss();
}
- dismiss();
}
@Override
@@ -157,7 +156,6 @@ public void onCancel(DialogInterface dialog) {
if (mListener != null) {
mListener.onCancel();
}
- dismiss();
}
private void initialize() {
diff --git a/app/src/main/java/com/afwsamples/testdpc/provision/PostProvisioningTask.java b/app/src/main/java/com/afwsamples/testdpc/provision/PostProvisioningTask.java
index be4de37b..53b93704 100644
--- a/app/src/main/java/com/afwsamples/testdpc/provision/PostProvisioningTask.java
+++ b/app/src/main/java/com/afwsamples/testdpc/provision/PostProvisioningTask.java
@@ -16,10 +16,6 @@
package com.afwsamples.testdpc.provision;
-import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
-import static com.afwsamples.testdpc.DeviceAdminReceiver.getComponentName;
-
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.TargetApi;
@@ -38,8 +34,7 @@
import com.afwsamples.testdpc.AddAccountActivity;
import com.afwsamples.testdpc.DeviceAdminReceiver;
-import com.afwsamples.testdpc.EnableDeviceOwnerActivity;
-import com.afwsamples.testdpc.EnableProfileActivity;
+import com.afwsamples.testdpc.FinalizeActivity;
import com.afwsamples.testdpc.common.LaunchIntentUtil;
import com.afwsamples.testdpc.common.Util;
import com.afwsamples.testdpc.cosu.EnableCosuActivity;
@@ -48,6 +43,10 @@
import java.util.Collections;
import java.util.List;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
+import static com.afwsamples.testdpc.DeviceAdminReceiver.getComponentName;
+
/**
* Task executed after provisioning is done indicated by either the
* {@link DevicePolicyManager#ACTION_PROVISIONING_SUCCESSFUL} activity intent or the
@@ -140,13 +139,11 @@ public Intent getPostProvisioningLaunchIntent(Intent intent) {
return null;
}
- if (isProfileOwner) {
- launch = new Intent(mContext, EnableProfileActivity.class);
- } else if (cosuLaunch) {
+ if (cosuLaunch) {
launch = new Intent(mContext, EnableCosuActivity.class);
launch.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, extras);
} else {
- launch = new Intent(mContext, EnableDeviceOwnerActivity.class);
+ launch = new Intent(mContext, FinalizeActivity.class);
}
if (synchronousAuthLaunch) {
diff --git a/app/src/main/java/com/afwsamples/testdpc/provision/ProvisioningUtil.java b/app/src/main/java/com/afwsamples/testdpc/provision/ProvisioningUtil.java
index 8eb742e6..85c85b64 100644
--- a/app/src/main/java/com/afwsamples/testdpc/provision/ProvisioningUtil.java
+++ b/app/src/main/java/com/afwsamples/testdpc/provision/ProvisioningUtil.java
@@ -21,12 +21,10 @@
import android.content.Context;
import com.afwsamples.testdpc.DeviceAdminReceiver;
-import com.afwsamples.testdpc.FirstAccountReadyBroadcastReceiver;
import com.afwsamples.testdpc.R;
public class ProvisioningUtil {
public static void enableProfile(Context context) {
- FirstAccountReadyBroadcastReceiver.cancelFirstAccountReadyTimeoutAlarm(context);
DevicePolicyManager manager = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
ComponentName componentName = DeviceAdminReceiver.getComponentName(context);
diff --git a/app/src/main/java/com/afwsamples/testdpc/safetynet/SafetyNetFragment.java b/app/src/main/java/com/afwsamples/testdpc/safetynet/SafetyNetFragment.java
deleted file mode 100644
index 9829ef03..00000000
--- a/app/src/main/java/com/afwsamples/testdpc/safetynet/SafetyNetFragment.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.afwsamples.testdpc.safetynet;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.support.annotation.ColorInt;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.text.method.ScrollingMovementMethod;
-import android.util.Base64;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-import com.afwsamples.testdpc.R;
-import com.google.android.gms.common.ConnectionResult;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.ResultCallbacks;
-import com.google.android.gms.common.api.Status;
-import com.google.android.gms.safetynet.SafetyNet;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.security.SecureRandom;
-
-import static com.google.android.gms.safetynet.SafetyNetApi.AttestationResult;
-
-/**
- * Demonstrate how to use SafetyNet API to check device compatibility.
- * Please notice that you should verifying the payload in your server.
- * For more details, please check http://developer.android.com/training/safetynet/index.html.
- */
-public class SafetyNetFragment extends DialogFragment implements
- GoogleApiClient.ConnectionCallbacks,
- GoogleApiClient.OnConnectionFailedListener {
- private GoogleApiClient mGoogleApiClient;
- private TextView mMessageView;
- private @ColorInt int BLACK, DARK_RED;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Kick start the checking
- mGoogleApiClient = buildGoogleApiClient();
- }
-
- @Override
- public void onStart() {
- super.onStart();
- updateMessageView(R.string.safetynet_running, false);
- mGoogleApiClient.connect();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- mGoogleApiClient.disconnect();
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- BLACK = ContextCompat.getColor(getActivity(), R.color.text_black);
- DARK_RED = ContextCompat.getColor(getActivity(), R.color.dark_red);
- LayoutInflater inflater = LayoutInflater.from(getActivity());
- View rootView = inflater.inflate(R.layout.safety_net_attest_dialog, null);
- mMessageView = (TextView) rootView.findViewById(R.id.message_view);
- // Show scrollbar in textview.
- mMessageView.setMovementMethod(new ScrollingMovementMethod());
- return new AlertDialog.Builder(getActivity())
- .setView(rootView)
- .setTitle(R.string.safetynet_dialog_title)
- .setNeutralButton(android.R.string.ok, null)
- .create();
- }
-
- @Override
- public void onConnected(@Nullable Bundle bundle) {
- if (hasInternetConnection()) {
- runSaftyNetTest();
- } else {
- updateMessageView(R.string.safetynet_fail_reason_no_internet, true);
- }
- }
-
- @Override
- public void onConnectionSuspended(int i) {
- updateMessageView(R.string.cancel_safetynet_msg, true);
- }
-
- @Override
- public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
- if (connectionResult.getErrorCode() == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED) {
- updateMessageView(R.string.safetynet_fail_reason_gmscore_upgrade, true);
- } else {
- updateMessageView(getString(R.string.safetynet_fail_reason_error_code,
- connectionResult.getErrorCode()), true);
- }
- }
-
- private GoogleApiClient buildGoogleApiClient() {
- return new GoogleApiClient.Builder(getActivity())
- .addApi(SafetyNet.API)
- .addConnectionCallbacks(this)
- .addOnConnectionFailedListener(this)
- .build();
- }
-
- /**
- * For simplicity, we generate the nonce in the client. However, it should be generated on the
- * server for anti-replay protection.
- */
- private byte[] generateNonce() {
- byte[] nonce = new byte[32];
- SecureRandom secureRandom = new SecureRandom();
- secureRandom.nextBytes(nonce);
- return nonce;
- }
-
- private void runSaftyNetTest() {
- final byte[] nonce = generateNonce();
- SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)
- .setResultCallback(new ResultCallbacks() {
- @Override
- public void onSuccess(@NonNull AttestationResult attestationResult) {
- if (isDetached()) {
- return;
- }
- final String jws = attestationResult.getJwsResult();
- try {
- final JSONObject jsonObject = retrievePayloadFromJws(jws);
- final String jsonString = jsonObject.toString(4);
- final String verifyOnServerString
- = getString(R.string.safetynet_verify_on_server);
- updateMessageView(verifyOnServerString + "\n" + jsonString, false);
- } catch (JSONException ex) {
- updateMessageView(R.string.safetynet_fail_reason_invalid_jws, true);
- }
- }
-
- @Override
- public void onFailure(@NonNull Status status) {
- if (isDetached()) {
- return;
- }
- updateMessageView(R.string.safetynet_fail_to_run_api, true);
- }
- });
- }
-
- private void updateMessageView(int message, boolean isError) {
- updateMessageView(getString(message), isError);
- }
-
- private void updateMessageView(String message, boolean isError) {
- mMessageView.setText(message);
- mMessageView.setTextColor((isError) ? DARK_RED : BLACK);
- }
-
- private boolean hasInternetConnection() {
- ConnectivityManager cm =
- (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
- return activeNetwork != null && activeNetwork.isConnected();
- }
-
- private static JSONObject retrievePayloadFromJws(String jws) throws JSONException {
- String[] parts = jws.split("\\.");
- if (parts.length != 3) {
- throw new JSONException("Invalid JWS");
- }
- return new JSONObject(new String(Base64.decode(parts[1], Base64.URL_SAFE)));
- }
-}
diff --git a/app/src/main/java/com/afwsamples/testdpc/search/PreferenceXmlUtil.java b/app/src/main/java/com/afwsamples/testdpc/search/PreferenceXmlUtil.java
index 0434efda..9eab71f2 100644
--- a/app/src/main/java/com/afwsamples/testdpc/search/PreferenceXmlUtil.java
+++ b/app/src/main/java/com/afwsamples/testdpc/search/PreferenceXmlUtil.java
@@ -5,38 +5,29 @@
import android.util.AttributeSet;
import android.util.TypedValue;
-import java.lang.reflect.Field;
-
/**
* Util class to retrieve some values of attributes in preference xml.
* To achieve this, we need to:
- * 1. Obtain the array android.R$styleable.Preference through reflection.
- * Cache is introduced to reduce the performance overhead introduced by reflection.
- * 2. Obtain the resource id of certain attributes that we care such as title and key using
- * reflection. Again, cache is introduced.
- * 3. Obtain the value of those attribute {@link TypedArray#peekValue(int)}.
+ * 1. Obtain the resource id of certain attributes that we care such as title and key.
+ * 2. Obtain the value of those attribute {@link TypedArray#peekValue(int)}.
*/
public class PreferenceXmlUtil {
- private static Integer sPreferenceTitleId;
- private static Integer sPreferenceKeyId;
- private static int[] sPreferenceStyleArray;
public static String getDataTitle(Context context, AttributeSet attrs)
throws ReflectiveOperationException {
- return getData(context, attrs, getPreferenceTitleId());
+ return getData(context, attrs, android.R.attr.title);
}
public static String getDataKey(Context context, AttributeSet attrs)
throws ReflectiveOperationException {
- return getData(context, attrs, getPreferenceKeyId());
+ return getData(context, attrs, android.R.attr.key);
}
- private static String getData(Context context, AttributeSet set, int resId)
+ private static String getData(Context context, AttributeSet set, int attribute)
throws ReflectiveOperationException {
- int[] attrs = getPreferenceStyleArray();
- final TypedArray sa = context.obtainStyledAttributes(set, attrs);
+ final TypedArray sa = context.obtainStyledAttributes(set, new int[] {attribute});
try {
- final TypedValue tv = sa.peekValue(resId);
+ final TypedValue tv = sa.peekValue(0);
CharSequence data = null;
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
@@ -50,35 +41,4 @@ private static String getData(Context context, AttributeSet set, int resId)
sa.recycle();
}
}
-
- private static int getPreferenceTitleId() throws ReflectiveOperationException {
- if (sPreferenceTitleId == null) {
- sPreferenceTitleId = getStyleableId("Preference_title");
- }
- return sPreferenceTitleId;
- }
-
- private static int getPreferenceKeyId() throws ReflectiveOperationException {
- if (sPreferenceKeyId == null) {
- sPreferenceKeyId = getStyleableId("Preference_key");
- }
- return sPreferenceKeyId;
- }
-
- private static int[] getPreferenceStyleArray() throws ReflectiveOperationException {
- if (sPreferenceStyleArray == null) {
- sPreferenceStyleArray = getStyleableArray("Preference");
- }
- return sPreferenceStyleArray;
- }
-
- private static int getStyleableId(String name) throws ReflectiveOperationException {
- Field field = Class.forName("android.R$styleable").getDeclaredField(name);
- return (int) field.get(null);
- }
-
- private static final int[] getStyleableArray(String name) throws ReflectiveOperationException {
- Field field = Class.forName("android.R$styleable").getDeclaredField(name);
- return (int[]) field.get(null);
- }
}
diff --git a/app/src/main/res/drawable/ic_enterprise_blue.xml b/app/src/main/res/drawable/ic_enterprise_blue.xml
new file mode 100644
index 00000000..da7057a1
--- /dev/null
+++ b/app/src/main/res/drawable/ic_enterprise_blue.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_add_account.xml b/app/src/main/res/layout/activity_add_account.xml
index c0bb0190..18e5e395 100644
--- a/app/src/main/res/layout/activity_add_account.xml
+++ b/app/src/main/res/layout/activity_add_account.xml
@@ -1,5 +1,4 @@
-
-
-
+
+
+ android:orientation="vertical">
-
+
+
-
+
+
+
+
+ android:text="@string/add_account_with_name" />
-
-
-
-
+ android:text="@string/add_account_skip" />
-
+
diff --git a/app/src/main/res/layout/enable_cosu_activity.xml b/app/src/main/res/layout/enable_cosu_activity.xml
index 6cdbd770..077fe187 100644
--- a/app/src/main/res/layout/enable_cosu_activity.xml
+++ b/app/src/main/res/layout/enable_cosu_activity.xml
@@ -21,7 +21,6 @@
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- style="@style/SetupIllustrationTheme"
app:suwHeaderText="@string/setup_cosu">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/enable_profile_activity.xml b/app/src/main/res/layout/enable_profile_activity.xml
deleted file mode 100644
index cb552cdb..00000000
--- a/app/src/main/res/layout/enable_profile_activity.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/finalize_activity.xml b/app/src/main/res/layout/finalize_activity.xml
new file mode 100644
index 00000000..59328ca3
--- /dev/null
+++ b/app/src/main/res/layout/finalize_activity.xml
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/insert_apn.xml b/app/src/main/res/layout/insert_apn.xml
index c70f4b89..7e0e9bc6 100644
--- a/app/src/main/res/layout/insert_apn.xml
+++ b/app/src/main/res/layout/insert_apn.xml
@@ -186,12 +186,11 @@
android:layout_height="wrap_content"
android:text="@string/apn_auth_type"
style="@style/networking_item_label"/>
-
+
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/next_footer.xml b/app/src/main/res/layout/next_footer.xml
new file mode 100644
index 00000000..467957ce
--- /dev/null
+++ b/app/src/main/res/layout/next_footer.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/setup_footer.xml b/app/src/main/res/layout/setup_footer.xml
new file mode 100644
index 00000000..71f98e62
--- /dev/null
+++ b/app/src/main/res/layout/setup_footer.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/setup_management_fragment.xml b/app/src/main/res/layout/setup_management_fragment.xml
index 50bdd2a3..d31da7fb 100644
--- a/app/src/main/res/layout/setup_management_fragment.xml
+++ b/app/src/main/res/layout/setup_management_fragment.xml
@@ -1,73 +1,82 @@
-
+
+
+ android:orientation="vertical">
-
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+ android:text="@string/set_up_device_owner"
+ android:visibility="gone" />
-
-
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 9e5c8e4f..610bca7a 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -25,4 +25,7 @@
#D3D3D3
#D32F2F
#388E3C
+ #ff254FAE
+ #ff3367d6
+ #ff3367d6
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e872893f..4ba26f71 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -217,29 +217,67 @@
Enable override APNs
Entry name
APN name
- Proxy
- Port
+ Proxy address
+ Proxy port
MMSC
- MMS Proxy
- MMS Port
+ MMS proxy address
+ MMS proxy port
User
Password
Authentication type
- Type
- Numeric(MCC+MNC)
+ Apn type bitmask
+ Operator numeric(MCC+MNC)
Protocol
Roaming protocol
Carrier enabled
- Network bitmask
+ Network type bitmask
MVNO type
- 0:None, 1:PAP, 2:CHAP, 3:PAP_OR_CHAP
Numeric=MCC+MNC
- 0 for false, 1 for true
- Entry name is not specified
- APN name is not specified
+
+ Entry name cannot be empty
+ APN name cannot be empty
+ Apn type bitmask cannot be empty or zero
Cannot parse mmsc
- Cannot parse proxy or mmsproxy
- Cannot parse port or mmsport
+ Cannot parse proxy address or MMS proxy address
+ Cannot parse proxy port or MMS proxy port
+
+
+ - Not specified
+
+ - NONE
+
+ - PAP
+
+ - CHAP
+
+ - PAP or CHAP
+
+
+ - Not specified
+
+ - IP
+
+ - IPV6
+
+ - IPV4V6
+
+ - PPP
+
+
+ - Not specified
+
+ - SPN
+
+ - IMSI
+
+ - GID
+
+ - ICCID
+
+
+ - Disabled
+ - Enabled
+
WI-FI management
@@ -546,8 +584,6 @@
Enable backup service
- Make backups mandatory
- Select mandatory backup account
Enable security logging
@@ -831,21 +867,6 @@
Minimum number of symbols
Minimum number of non-letters
-
- Password blacklist
- Set password blacklist
- Load password blacklist from file
- Must be one password per line
- Clear password blacklist
- No blacklist to clear
-
- Password blacklist manager
- Enter restricted password
- Cannot add empty item to blacklist
- Failed to load blacklist file
- Failed to save password blacklist
- Saved password blacklist
-
Password is not compliant
Separate work challenge required
Tap to set a new lock screen password
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 1b8554dd..f449125c 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,41 +1,30 @@
-
-
-
-