Adding unlockProfile to trust-agent meta data and makes TrustAgent runnable under direct boot
Test: manual
Change-Id: I1f0ccafac08be2cc3f4540232e764ef21d4fed38
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2d61e6e..d03f2e7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7442,6 +7442,8 @@
<attr name="title" />
<!-- @SystemApi Summary for the same preference as the title. @hide -->
<attr name="summary" />
+ <!-- @SystemApi Whether trust agent can unlock a user profile @hide -->
+ <attr name="unlockProfile" format="boolean"/>
</declare-styleable>
<!-- =============================== -->
@@ -8312,13 +8314,13 @@
<attr name="color" />
</declare-styleable>
- <!-- @hide Attributes which will be read by the Activity to intialize the
+ <!-- @hide Attributes which will be read by the Activity to intialize the
base activity TaskDescription. -->
<declare-styleable name="ActivityTaskDescription">
<!-- @hide From Theme.colorPrimary, used for the TaskDescription primary
color. -->
<attr name="colorPrimary" />
- <!-- @hide From Theme.colorBackground, used for the TaskDescription background
+ <!-- @hide From Theme.colorBackground, used for the TaskDescription background
color. -->
<attr name="colorBackground" />
</declare-styleable>
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index a7c9105..edcea0e 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -24,6 +24,7 @@
android:name=".SampleTrustAgent"
android:label="@string/app_name"
android:permission="android.permission.BIND_TRUST_AGENT"
+ android:directBootAware="true"
android:exported="true">
<intent-filter>
<action android:name="android.service.trust.TrustAgentService" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml
new file mode 100644
index 0000000..4669971
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout-v26/sample_trust_agent_settings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button android:id="@+id/enable_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Grant trust for 30 seconds" />
+ <Button android:id="@+id/revoke_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Revoke trust" />
+ <Button android:id="@+id/crash"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Crash" />
+ <CheckBox android:id="@+id/managing_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust" />
+ <CheckBox android:id="@+id/managing_trust_direct_boot"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Managing trust direct boot"/>
+
+ <CheckBox android:id="@+id/report_unlock_attempts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report unlock attempts" />
+ <CheckBox android:id="@+id/report_device_locked"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:text="Report device locked or unlocked" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <Button android:id="@+id/check_device_locked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Device locked?" />
+ <TextView android:id="@+id/check_device_locked_result"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
new file mode 100644
index 0000000..26d5aa0
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml-v26/sample_trust_agent.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity=".SampleTrustAgentSettings"
+ android:unlockProfile="true" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
index b363ab4..6cd34bb 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
@@ -15,4 +15,4 @@
~ limitations under the License
-->
<trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity=".SampleTrustAgentSettings" />
+ android:settingsActivity=".SampleTrustAgentSettings" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index b8f16e7..4b50cf8 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -22,6 +22,7 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.PersistableBundle;
+import android.os.UserManager;
import android.preference.PreferenceManager;
import android.service.trust.TrustAgentService;
import android.support.v4.content.LocalBroadcastManager;
@@ -57,26 +58,47 @@
= "preference.report_unlock_attempts";
private static final String PREFERENCE_MANAGING_TRUST
= "preference.managing_trust";
+ private static final String PREFERENCE_MANAGING_TRUST_DIRECT_BOOT
+ = "preference.managing_trust_direct_boot";
private static final String PREFERENCE_REPORT_DEVICE_LOCKED = "preference.report_device_locked";
private static final String TAG = "SampleTrustAgent";
+ private static final BroadcastReceiver mUnlockReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ }
+ };
+
+ private boolean mIsUserUnlocked;
+
@Override
public void onCreate() {
super.onCreate();
+ UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+ mIsUserUnlocked = um.isUserUnlocked();
+ Log.i(TAG,, "onCreate, is user unlocked=" + mIsUserUnlocked);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_GRANT_TRUST);
filter.addAction(ACTION_REVOKE_TRUST);
+ if (!mIsUserUnlocked) {
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ }
mLocalBroadcastManager.registerReceiver(mReceiver, filter);
if (ALLOW_EXTERNAL_BROADCASTS) {
registerReceiver(mReceiver, filter);
}
- setManagingTrust(getIsManagingTrust(this));
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(this);
+ if (!mIsUserUnlocked) {
+ boolean trustManaged = getIsManagingTrustDirectBoot(this);
+ Log.i(TAG, "in Direct boot." + (trustManaged ? "manage" : "cannot manage") + "trust");
+ setManagingTrust(getIsManagingTrustDirectBoot(this));
+ } else {
+ onBootCompleted();
+ }
}
@Override
@@ -137,6 +159,12 @@
.unregisterOnSharedPreferenceChangeListener(this);
}
+ private void onBootCompleted() {
+ PreferenceManager.getDefaultSharedPreferences(this)
+ .registerOnSharedPreferenceChangeListener(this);
+ setManagingTrust(getIsManagingTrust(this));
+ }
+
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -158,6 +186,9 @@
}
} else if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
+ } else if (intent.ACTION_BOOT_COMPLETED.equals(action)) {
+ Log.d(TAG, "User unlocked and boot completed.");
+ onBootCompleted();
}
}
};
@@ -203,6 +234,7 @@
public static void setIsManagingTrust(Context context, boolean enabled) {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(context);
+ Log.d("AAAA", "save manage trust preference. Enabled=" + enabled);
sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST, enabled).apply();
}
@@ -212,6 +244,21 @@
return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST, false);
}
+ public static void setIsManagingTrustDirectBoot(Context context, boolean enabled) {
+ Context directBootContext = context.createDeviceProtectedStorageContext();
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(directBootContext);
+ Log.d("AAAA", "save to direct boot preference. Enabled=" + enabled);
+ sharedPreferences.edit().putBoolean(PREFERENCE_MANAGING_TRUST_DIRECT_BOOT, enabled).apply();
+ }
+
+ public static boolean getIsManagingTrustDirectBoot(Context context) {
+ Context directBootContext = context.createDeviceProtectedStorageContext();
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(directBootContext);
+ return sharedPreferences.getBoolean(PREFERENCE_MANAGING_TRUST_DIRECT_BOOT, false);
+ }
+
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (PREFERENCE_MANAGING_TRUST.equals(key)) {
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 29b15cb..1b17169 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -33,6 +33,7 @@
private CheckBox mReportUnlockAttempts;
private CheckBox mReportDeviceLocked;
private CheckBox mManagingTrust;
+ private CheckBox mManagingTrustDirectBoot;
private TextView mCheckDeviceLockedResult;
private KeyguardManager mKeyguardManager;
@@ -59,6 +60,8 @@
mManagingTrust = (CheckBox) findViewById(R.id.managing_trust);
mManagingTrust.setOnCheckedChangeListener(this);
+ mManagingTrustDirectBoot = (CheckBox) findViewById(R.id.managing_trust_direct_boot);
+ mManagingTrustDirectBoot.setOnCheckedChangeListener(this);
mCheckDeviceLockedResult = (TextView) findViewById(R.id.check_device_locked_result);
}
@@ -68,6 +71,8 @@
super.onResume();
mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
mManagingTrust.setChecked(SampleTrustAgent.getIsManagingTrust(this));
+ mManagingTrustDirectBoot.setChecked(
+ SampleTrustAgent.getIsManagingTrustDirectBoot(this));
updateTrustedState();
}
@@ -94,6 +99,8 @@
SampleTrustAgent.setIsManagingTrust(this, isChecked);
} else if (buttonView == mReportDeviceLocked) {
SampleTrustAgent.setReportDeviceLocked(this, isChecked);
+ } else if (buttonView == mManagingTrustDirectBoot) {
+ SampleTrustAgent.setIsManagingTrustDirectBoot(this, isChecked);
}
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 9d02940..cca8cc8 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -169,7 +169,7 @@
CharSequence label;
Drawable icon;
ComponentName component; // service that implements ITrustAgent
- ComponentName settings; // setting to launch to modify agent.
+ SettingsAttrs settings; // setting to launch to modify agent.
TrustAgentWrapper agent;
int userId;
@@ -258,11 +258,6 @@
+ ": switchToByUser=false");
continue;
}
- if (!StorageManager.isUserKeyUnlocked(userInfo.id)) {
- if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
- + ": FDE still locked");
- continue;
- }
if (!mActivityManager.isUserRunning(userInfo.id)) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": user not started");
@@ -273,13 +268,7 @@
+ ": no secure credential");
continue;
}
- if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) {
- if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
- + ": prevented by StrongAuthTracker = 0x"
- + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser(
- userInfo.id)));
- continue;
- }
+
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
@@ -312,16 +301,49 @@
continue;
}
}
-
AgentInfo agentInfo = new AgentInfo();
agentInfo.component = name;
agentInfo.userId = userInfo.id;
if (!mActiveAgents.contains(agentInfo)) {
agentInfo.label = resolveInfo.loadLabel(pm);
agentInfo.icon = resolveInfo.loadIcon(pm);
- agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
+ agentInfo.settings = getSettingsAttrs(pm, resolveInfo);
agentInfo.agent = new TrustAgentWrapper(mContext, this,
new Intent().setComponent(name), userInfo.getUserHandle());
+ } else {
+ int index = mActiveAgents.indexOf(agentInfo);
+ agentInfo = mActiveAgents.valueAt(index);
+ }
+
+ boolean directUnlock = resolveInfo.serviceInfo.directBootAware
+ && agentInfo.settings.canUnlockProfile;
+
+ if (directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: trustagent " + name
+ + "of user " + userInfo.id + "can unlock user profile.");
+ }
+
+ if (!StorageManager.isUserKeyUnlocked(userInfo.id)
+ && !directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ + "'s trust agent " + name + ": FDE still locked and "
+ + " the agent cannot unlock user profile.");
+ continue;
+ }
+
+ if (!mStrongAuthTracker.canAgentsRunForUser(userInfo.id)) {
+ int flag = mStrongAuthTracker.getStrongAuthForUser(userInfo.id);
+ if (flag != StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
+ || !directUnlock) {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ + ": prevented by StrongAuthTracker = 0x"
+ + Integer.toHexString(mStrongAuthTracker.getStrongAuthForUser(
+ userInfo.id)));
+ continue;
+ }
+ }
+
+ if (!mActiveAgents.contains(agentInfo)) {
mActiveAgents.add(agentInfo);
} else {
obsoleteAgents.remove(agentInfo);
@@ -468,10 +490,12 @@
refreshAgentList(userId);
}
- private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
+ private SettingsAttrs getSettingsAttrs(PackageManager pm, ResolveInfo resolveInfo) {
if (resolveInfo == null || resolveInfo.serviceInfo == null
|| resolveInfo.serviceInfo.metaData == null) return null;
String cn = null;
+ boolean canUnlockProfile = false;
+
XmlResourceParser parser = null;
Exception caughtException = null;
try {
@@ -496,6 +520,8 @@
TypedArray sa = res
.obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
+ canUnlockProfile = sa.getBoolean(
+ com.android.internal.R.styleable.TrustAgent_unlockProfile, false);
sa.recycle();
} catch (PackageManager.NameNotFoundException e) {
caughtException = e;
@@ -516,7 +542,7 @@
if (cn.indexOf('/') < 0) {
cn = resolveInfo.serviceInfo.packageName + "/" + cn;
}
- return ComponentName.unflattenFromString(cn);
+ return new SettingsAttrs(ComponentName.unflattenFromString(cn), canUnlockProfile);
}
private ComponentName getComponentName(ResolveInfo resolveInfo) {
@@ -554,6 +580,7 @@
private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) {
List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+ PackageManager.GET_META_DATA |
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId);
ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size());
@@ -991,6 +1018,18 @@
}
};
+ private static class SettingsAttrs {
+ public ComponentName componentName;
+ public boolean canUnlockProfile;
+
+ public SettingsAttrs(
+ ComponentName componentName,
+ boolean canUnlockProfile) {
+ this.componentName = componentName;
+ this.canUnlockProfile = canUnlockProfile;
+ }
+ };
+
private class Receiver extends BroadcastReceiver {
@Override