Adding unlockProfile to trust-agent meta data and makes TrustAgent runnable under direct boot
Test: manual Change-Id: I1f0ccafac08be2cc3f4540232e764ef21d4fed38
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
@@ -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" />
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user