Adding unlockProfile to trust-agent meta data and makes TrustAgent runnable under direct boot

Test: manual
Change-Id: I1f0ccafac08be2cc3f4540232e764ef21d4fed38
This commit is contained in:
Lingjun Li
2016-11-14 15:39:13 -08:00
parent 99820db99a
commit 20914d7939
8 changed files with 212 additions and 23 deletions

View File

@@ -7442,6 +7442,8 @@ i
<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 @@ i
<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>

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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" />

View File

@@ -22,6 +22,7 @@ import android.content.Intent;
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 @@ public class SampleTrustAgent extends TrustAgentService
= "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 @@ public class SampleTrustAgent extends TrustAgentService
.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 @@ public class SampleTrustAgent extends TrustAgentService
}
} 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 class SampleTrustAgent extends TrustAgentService
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 @@ public class SampleTrustAgent extends TrustAgentService
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)) {

View File

@@ -33,6 +33,7 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
private CheckBox mReportUnlockAttempts;
private CheckBox mReportDeviceLocked;
private CheckBox mManagingTrust;
private CheckBox mManagingTrustDirectBoot;
private TextView mCheckDeviceLockedResult;
private KeyguardManager mKeyguardManager;
@@ -59,6 +60,8 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
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 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
super.onResume();
mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
mManagingTrust.setChecked(SampleTrustAgent.getIsManagingTrust(this));
mManagingTrustDirectBoot.setChecked(
SampleTrustAgent.getIsManagingTrustDirectBoot(this));
updateTrustedState();
}
@@ -94,6 +99,8 @@ public class SampleTrustAgentSettings extends Activity implements View.OnClickLi
SampleTrustAgent.setIsManagingTrust(this, isChecked);
} else if (buttonView == mReportDeviceLocked) {
SampleTrustAgent.setReportDeviceLocked(this, isChecked);
} else if (buttonView == mManagingTrustDirectBoot) {
SampleTrustAgent.setIsManagingTrustDirectBoot(this, isChecked);
}
}

View File

@@ -169,7 +169,7 @@ public class TrustManagerService extends SystemService {
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 @@ public class TrustManagerService extends SystemService {
+ ": 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 @@ public class TrustManagerService extends SystemService {
+ ": 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 @@ public class TrustManagerService extends SystemService {
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 @@ public class TrustManagerService extends SystemService {
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 @@ public class TrustManagerService extends SystemService {
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 @@ public class TrustManagerService extends SystemService {
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 @@ public class TrustManagerService extends SystemService {
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 @@ public class TrustManagerService extends SystemService {
}
};
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