TrustManagerService.java

时间:2022-08-28 12:40:47
 /*
* 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
*/ package com.android.server.trust; import android.Manifest;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Build;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; /**
* Manages trust agents and trust listeners.
*
* It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
* of each user and notifies them about events that are relevant to them.
* It start and stops them based on the value of
* {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
*
* It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
* trust state changes for any user.
*
* Trust state and the setting of enabled agents is kept per user and each user has its own
* instance of a {@link android.service.trust.TrustAgentService}.
*/
public class TrustManagerService extends SystemService {
private static final String TAG = "TrustManagerService";
static final boolean DEBUG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE); private static final Intent TRUST_AGENT_INTENT =
new Intent(TrustAgentService.SERVICE_INTERFACE);
private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT; private static final int MSG_REGISTER_LISTENER = 1;
private static final int MSG_UNREGISTER_LISTENER = 2;
private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
private static final int MSG_START_USER = 7;
private static final int MSG_CLEANUP_USER = 8;
private static final int MSG_SWITCH_USER = 9;
private static final int MSG_FLUSH_TRUST_USUALLY_MANAGED = 10;
private static final int MSG_UNLOCK_USER = 11;
private static final int MSG_STOP_USER = 12;
private static final int MSG_DISPATCH_UNLOCK_LOCKOUT = 13;
private static final int MSG_REFRESH_DEVICE_LOCKED_FOR_USER = 14; private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000; private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
private final Receiver mReceiver = new Receiver(); /* package */ final TrustArchive mArchive = new TrustArchive();
private final Context mContext;
private final LockPatternUtils mLockPatternUtils;
private final UserManager mUserManager;
private final ActivityManager mActivityManager; @GuardedBy("mUserIsTrusted")
private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray(); @GuardedBy("mDeviceLockedForUser")
private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray(); @GuardedBy("mTrustUsuallyManagedForUser")
private final SparseBooleanArray mTrustUsuallyManagedForUser = new SparseBooleanArray(); // set to true only if user can skip bouncer
@GuardedBy("mUsersUnlockedByFingerprint")
private final SparseBooleanArray mUsersUnlockedByFingerprint = new SparseBooleanArray(); private final StrongAuthTracker mStrongAuthTracker; private boolean mTrustAgentsCanRun = false;
private int mCurrentUser = UserHandle.USER_SYSTEM; public TrustManagerService(Context context) {
super(context);
mContext = context;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mLockPatternUtils = new LockPatternUtils(context);
mStrongAuthTracker = new StrongAuthTracker(context);
} @Override
public void onStart() {
publishBinderService(Context.TRUST_SERVICE, mService);
} @Override
public void onBootPhase(int phase) {
if (isSafeMode()) {
// No trust agents in safe mode.
return;
}
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
mReceiver.register(mContext);
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
mTrustAgentsCanRun = true;
refreshAgentList(UserHandle.USER_ALL);
refreshDeviceLockedForUser(UserHandle.USER_ALL);
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_SYSTEM);
}
} // Agent management private static final class AgentInfo {
CharSequence label;
Drawable icon;
ComponentName component; // service that implements ITrustAgent
SettingsAttrs settings; // setting to launch to modify agent.
TrustAgentWrapper agent;
int userId; @Override
public boolean equals(Object other) {
if (!(other instanceof AgentInfo)) {
return false;
}
AgentInfo o = (AgentInfo) other;
return component.equals(o.component) && userId == o.userId;
} @Override
public int hashCode() {
return component.hashCode() * 31 + userId;
}
} private void updateTrustAll() {
List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
for (UserInfo userInfo : userInfos) {
updateTrust(userInfo.id, 0);
}
} public void updateTrust(int userId, int flags) {
boolean managed = aggregateIsTrustManaged(userId);
dispatchOnTrustManagedChanged(managed, userId);
if (mStrongAuthTracker.isTrustAllowedForUser(userId)
&& isTrustUsuallyManagedInternal(userId) != managed) {
updateTrustUsuallyManaged(userId, managed);
}
boolean trusted = aggregateIsTrusted(userId);
boolean changed;
synchronized (mUserIsTrusted) {
changed = mUserIsTrusted.get(userId) != trusted;
mUserIsTrusted.put(userId, trusted);
}
dispatchOnTrustChanged(trusted, userId, flags);
if (changed) {
refreshDeviceLockedForUser(userId);
}
} private void updateTrustUsuallyManaged(int userId, boolean managed) {
synchronized (mTrustUsuallyManagedForUser) {
mTrustUsuallyManagedForUser.put(userId, managed);
}
// Wait a few minutes before committing to flash, in case the trust agent is transiently not
// managing trust (crashed, needs to acknowledge DPM restrictions, etc).
mHandler.removeMessages(MSG_FLUSH_TRUST_USUALLY_MANAGED);
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MSG_FLUSH_TRUST_USUALLY_MANAGED),
TRUST_USUALLY_MANAGED_FLUSH_DELAY);
} public long addEscrowToken(byte[] token, int userId) {
return mLockPatternUtils.addEscrowToken(token, userId);
} public boolean removeEscrowToken(long handle, int userId) {
return mLockPatternUtils.removeEscrowToken(handle, userId);
} public boolean isEscrowTokenActive(long handle, int userId) {
return mLockPatternUtils.isEscrowTokenActive(handle, userId);
} public void unlockUserWithToken(long handle, byte[] token, int userId) {
mLockPatternUtils.unlockUserWithToken(handle, token, userId);
} void showKeyguardErrorMessage(CharSequence message) {
dispatchOnTrustError(message);
} void refreshAgentList(int userIdOrAll) {
if (DEBUG) Slog.d(TAG, "refreshAgentList(" + userIdOrAll + ")");
if (!mTrustAgentsCanRun) {
return;
}
if (userIdOrAll != UserHandle.USER_ALL && userIdOrAll < UserHandle.USER_SYSTEM) {
Log.e(TAG, "refreshAgentList(userId=" + userIdOrAll + "): Invalid user handle,"
+ " must be USER_ALL or a specific user.", new Throwable("here"));
userIdOrAll = UserHandle.USER_ALL;
}
PackageManager pm = mContext.getPackageManager(); List<UserInfo> userInfos;
if (userIdOrAll == UserHandle.USER_ALL) {
userInfos = mUserManager.getUsers(true /* excludeDying */);
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userIdOrAll));
}
LockPatternUtils lockPatternUtils = mLockPatternUtils; ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
obsoleteAgents.addAll(mActiveAgents); for (UserInfo userInfo : userInfos) {
if (userInfo == null || userInfo.partial || !userInfo.isEnabled()
|| userInfo.guestToRemove) continue;
if (!userInfo.supportsSwitchToByUser()) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": switchToByUser=false");
continue;
}
if (!mActivityManager.isUserRunning(userInfo.id)) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": user not started");
continue;
}
if (!lockPatternUtils.isSecure(userInfo.id)) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": no secure credential");
continue;
} DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
final boolean disableTrustAgents =
(disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
if (enabledAgents == null) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ ": no agents enabled by user");
continue;
}
List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id);
for (ResolveInfo resolveInfo : resolveInfos) {
ComponentName name = getComponentName(resolveInfo); if (!enabledAgents.contains(name)) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping "
+ name.flattenToShortString() + " u"+ userInfo.id
+ ": not enabled by user");
continue;
}
if (disableTrustAgents) {
List<PersistableBundle> config =
dpm.getTrustAgentConfiguration(null /* admin */, name, userInfo.id);
// Disable agent if no features are enabled.
if (config == null || config.isEmpty()) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping "
+ name.flattenToShortString() + " u"+ userInfo.id
+ ": not allowed by DPM");
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 = getSettingsAttrs(pm, resolveInfo);
} 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 (!mUserManager.isUserUnlockingOrUnlocked(userInfo.id)
&& !directUnlock) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: skipping user " + userInfo.id
+ "'s trust agent " + name + ": FBE 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_LOCKOUT) {
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 (agentInfo.agent == null) {
agentInfo.agent = new TrustAgentWrapper(mContext, this,
new Intent().setComponent(name), userInfo.getUserHandle());
} if (!mActiveAgents.contains(agentInfo)) {
mActiveAgents.add(agentInfo);
} else {
obsoleteAgents.remove(agentInfo);
}
}
} boolean trustMayHaveChanged = false;
for (int i = 0; i < obsoleteAgents.size(); i++) {
AgentInfo info = obsoleteAgents.valueAt(i);
if (userIdOrAll == UserHandle.USER_ALL || userIdOrAll == info.userId) {
if (info.agent.isManagingTrust()) {
trustMayHaveChanged = true;
}
info.agent.destroy();
mActiveAgents.remove(info);
}
} if (trustMayHaveChanged) {
if (userIdOrAll == UserHandle.USER_ALL) {
updateTrustAll();
} else {
updateTrust(userIdOrAll, 0);
}
}
} boolean isDeviceLockedInner(int userId) {
synchronized (mDeviceLockedForUser) {
return mDeviceLockedForUser.get(userId, true);
}
} private void refreshDeviceLockedForUser(int userId) {
if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) {
Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle,"
+ " must be USER_ALL or a specific user.", new Throwable("here"));
userId = UserHandle.USER_ALL;
}
List<UserInfo> userInfos;
if (userId == UserHandle.USER_ALL) {
userInfos = mUserManager.getUsers(true /* excludeDying */);
} else {
userInfos = new ArrayList<>();
userInfos.add(mUserManager.getUserInfo(userId));
} IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); for (int i = 0; i < userInfos.size(); i++) {
UserInfo info = userInfos.get(i); if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
|| !info.supportsSwitchToByUser()) {
continue;
} int id = info.id;
boolean secure = mLockPatternUtils.isSecure(id);
boolean trusted = aggregateIsTrusted(id);
boolean showingKeyguard = true;
boolean fingerprintAuthenticated = false; if (mCurrentUser == id) {
synchronized(mUsersUnlockedByFingerprint) {
fingerprintAuthenticated = mUsersUnlockedByFingerprint.get(id, false);
}
try {
showingKeyguard = wm.isKeyguardLocked();
} catch (RemoteException e) {
}
}
boolean deviceLocked = secure && showingKeyguard && !trusted &&
!fingerprintAuthenticated;
setDeviceLockedForUser(id, deviceLocked);
}
} private void setDeviceLockedForUser(@UserIdInt int userId, boolean locked) {
final boolean changed;
synchronized (mDeviceLockedForUser) {
changed = isDeviceLockedInner(userId) != locked;
mDeviceLockedForUser.put(userId, locked);
}
if (changed) {
dispatchDeviceLocked(userId, locked);
}
} private void dispatchDeviceLocked(int userId, boolean isLocked) {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo agent = mActiveAgents.valueAt(i);
if (agent.userId == userId) {
if (isLocked) {
agent.agent.onDeviceLocked();
} else{
agent.agent.onDeviceUnlocked();
}
}
}
} void updateDevicePolicyFeatures() {
boolean changed = false;
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
if (info.agent.isConnected()) {
info.agent.updateDevicePolicyFeatures();
changed = true;
}
}
if (changed) {
mArchive.logDevicePolicyChanged();
}
} private void removeAgentsOfPackage(String packageName) {
boolean trustMayHaveChanged = false;
for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
AgentInfo info = mActiveAgents.valueAt(i);
if (packageName.equals(info.component.getPackageName())) {
Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
if (info.agent.isManagingTrust()) {
trustMayHaveChanged = true;
}
info.agent.destroy();
mActiveAgents.removeAt(i);
}
}
if (trustMayHaveChanged) {
updateTrustAll();
}
} public void resetAgent(ComponentName name, int userId) {
boolean trustMayHaveChanged = false;
for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
AgentInfo info = mActiveAgents.valueAt(i);
if (name.equals(info.component) && userId == info.userId) {
Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
if (info.agent.isManagingTrust()) {
trustMayHaveChanged = true;
}
info.agent.destroy();
mActiveAgents.removeAt(i);
}
}
if (trustMayHaveChanged) {
updateTrust(userId, 0);
}
refreshAgentList(userId);
} 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 {
parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
TrustAgentService.TRUST_AGENT_META_DATA);
if (parser == null) {
Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
return null;
}
Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
// Drain preamble.
}
String nodeName = parser.getName();
if (!"trust-agent".equals(nodeName)) {
Slog.w(TAG, "Meta-data does not start with trust-agent tag");
return null;
}
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;
} catch (IOException e) {
caughtException = e;
} catch (XmlPullParserException e) {
caughtException = e;
} finally {
if (parser != null) parser.close();
}
if (caughtException != null) {
Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
return null;
}
if (cn == null) {
return null;
}
if (cn.indexOf('/') < 0) {
cn = resolveInfo.serviceInfo.packageName + "/" + cn;
}
return new SettingsAttrs(ComponentName.unflattenFromString(cn), canUnlockProfile);
} private ComponentName getComponentName(ResolveInfo resolveInfo) {
if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
} private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
return;
}
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
ComponentName defaultAgent = getDefaultFactoryTrustAgent(mContext);
boolean shouldUseDefaultAgent = defaultAgent != null;
ArraySet<ComponentName> discoveredAgents = new ArraySet<>(); if (shouldUseDefaultAgent) {
discoveredAgents.add(defaultAgent);
Log.i(TAG, "Enabling " + defaultAgent + " because it is a default agent.");
} else { // A default agent is not set; perform regular trust agent discovery
for (ResolveInfo resolveInfo : resolveInfos) {
ComponentName componentName = getComponentName(resolveInfo);
int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
Log.i(TAG, "Leaving agent " + componentName + " disabled because package "
+ "is not a system package.");
continue;
}
discoveredAgents.add(componentName);
}
} List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
if (previouslyEnabledAgents != null) {
discoveredAgents.addAll(previouslyEnabledAgents);
}
utils.setEnabledTrustAgents(discoveredAgents, userId);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
} /**
* Returns the {@link ComponentName} for the default trust agent, or {@code null} if there
* is no trust agent set.
*/
private static ComponentName getDefaultFactoryTrustAgent(Context context) {
String defaultTrustAgent = context.getResources()
.getString(com.android.internal.R.string.config_defaultTrustAgent);
if (TextUtils.isEmpty(defaultTrustAgent)) {
return null;
}
return ComponentName.unflattenFromString(defaultTrustAgent);
} 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());
for (ResolveInfo resolveInfo : resolveInfos) {
if (resolveInfo.serviceInfo == null) continue;
if (resolveInfo.serviceInfo.applicationInfo == null) continue;
String packageName = resolveInfo.serviceInfo.packageName;
if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
!= PackageManager.PERMISSION_GRANTED) {
ComponentName name = getComponentName(resolveInfo);
Log.w(TAG, "Skipping agent " + name + " because package does not have"
+ " permission " + PERMISSION_PROVIDE_AGENT + ".");
continue;
}
allowedAgents.add(resolveInfo);
}
return allowedAgents;
} // Agent dispatch and aggregation private boolean aggregateIsTrusted(int userId) {
if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
return false;
}
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
if (info.userId == userId) {
if (info.agent.isTrusted()) {
return true;
}
}
}
return false;
} private boolean aggregateIsTrustManaged(int userId) {
if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
return false;
}
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
if (info.userId == userId) {
if (info.agent.isManagingTrust()) {
return true;
}
}
}
return false;
} private void dispatchUnlockAttempt(boolean successful, int userId) {
if (successful) {
mStrongAuthTracker.allowTrustFromUnlock(userId);
} for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
if (info.userId == userId) {
info.agent.onUnlockAttempt(successful);
}
}
} private void dispatchUnlockLockout(int timeoutMs, int userId) {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
if (info.userId == userId) {
info.agent.onUnlockLockout(timeoutMs);
}
}
} // Listeners private void addListener(ITrustListener listener) {
for (int i = 0; i < mTrustListeners.size(); i++) {
if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
return;
}
}
mTrustListeners.add(listener);
updateTrustAll();
} private void removeListener(ITrustListener listener) {
for (int i = 0; i < mTrustListeners.size(); i++) {
if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
mTrustListeners.remove(i);
return;
}
}
} private void dispatchOnTrustChanged(boolean enabled, int userId, int flags) {
if (DEBUG) {
Log.i(TAG, "onTrustChanged(" + enabled + ", " + userId + ", 0x"
+ Integer.toHexString(flags) + ")");
}
if (!enabled) flags = 0;
for (int i = 0; i < mTrustListeners.size(); i++) {
try {
mTrustListeners.get(i).onTrustChanged(enabled, userId, flags);
} catch (DeadObjectException e) {
Slog.d(TAG, "Removing dead TrustListener.");
mTrustListeners.remove(i);
i--;
} catch (RemoteException e) {
Slog.e(TAG, "Exception while notifying TrustListener.", e);
}
}
} private void dispatchOnTrustManagedChanged(boolean managed, int userId) {
if (DEBUG) {
Log.i(TAG, "onTrustManagedChanged(" + managed + ", " + userId + ")");
}
for (int i = 0; i < mTrustListeners.size(); i++) {
try {
mTrustListeners.get(i).onTrustManagedChanged(managed, userId);
} catch (DeadObjectException e) {
Slog.d(TAG, "Removing dead TrustListener.");
mTrustListeners.remove(i);
i--;
} catch (RemoteException e) {
Slog.e(TAG, "Exception while notifying TrustListener.", e);
}
}
} private void dispatchOnTrustError(CharSequence message) {
if (DEBUG) {
Log.i(TAG, "onTrustError(" + message + ")");
}
for (int i = 0; i < mTrustListeners.size(); i++) {
try {
mTrustListeners.get(i).onTrustError(message);
} catch (DeadObjectException e) {
Slog.d(TAG, "Removing dead TrustListener.");
mTrustListeners.remove(i);
i--;
} catch (RemoteException e) {
Slog.e(TAG, "Exception while notifying TrustListener.", e);
}
}
} // User lifecycle @Override
public void onStartUser(int userId) {
mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
} @Override
public void onCleanupUser(int userId) {
mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
} @Override
public void onSwitchUser(int userId) {
mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
} @Override
public void onUnlockUser(int userId) {
mHandler.obtainMessage(MSG_UNLOCK_USER, userId, 0, null).sendToTarget();
} @Override
public void onStopUser(@UserIdInt int userId) {
mHandler.obtainMessage(MSG_STOP_USER, userId, 0, null).sendToTarget();
} // Plumbing private final IBinder mService = new ITrustManager.Stub() {
@Override
public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
enforceReportPermission();
mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
.sendToTarget();
} @Override
public void reportUnlockLockout(int timeoutMs, int userId) throws RemoteException {
enforceReportPermission();
mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_LOCKOUT, timeoutMs, userId)
.sendToTarget();
} @Override
public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
enforceReportPermission();
// coalesce refresh messages.
mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
} @Override
public void reportKeyguardShowingChanged() throws RemoteException {
enforceReportPermission();
// coalesce refresh messages.
mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED); // Make sure handler processes the message before returning, such that isDeviceLocked
// after this call will retrieve the correct value.
mHandler.runWithScissors(() -> {}, 0);
} @Override
public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
enforceListenerPermission();
mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
} @Override
public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
enforceListenerPermission();
mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
} @Override
public boolean isDeviceLocked(int userId) throws RemoteException {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false /* allowAll */, true /* requireFull */, "isDeviceLocked", null); long token = Binder.clearCallingIdentity();
try {
if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
userId = resolveProfileParent(userId);
}
return isDeviceLockedInner(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
} @Override
public boolean isDeviceSecure(int userId) throws RemoteException {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false /* allowAll */, true /* requireFull */, "isDeviceSecure", null); long token = Binder.clearCallingIdentity();
try {
if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
userId = resolveProfileParent(userId);
}
return mLockPatternUtils.isSecure(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
} private void enforceReportPermission() {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
} private void enforceListenerPermission() {
mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
"register trust listener");
} @Override
protected void dump(FileDescriptor fd, final PrintWriter fout, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, fout)) return;
if (isSafeMode()) {
fout.println("disabled because the system is in safe mode.");
return;
}
if (!mTrustAgentsCanRun) {
fout.println("disabled because the third-party apps can't run yet.");
return;
}
final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
fout.println("Trust manager state:");
for (UserInfo user : userInfos) {
dumpUser(fout, user, user.id == mCurrentUser);
}
}
}, 1500);
} private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
fout.printf(" User \"%s\" (id=%d, flags=%#x)",
user.name, user.id, user.flags);
if (!user.supportsSwitchToByUser()) {
fout.println("(managed profile)");
fout.println(" disabled because switching to this user is not possible.");
return;
}
if (isCurrent) {
fout.print(" (current)");
}
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
fout.print(", strongAuthRequired=" + dumpHex(
mStrongAuthTracker.getStrongAuthForUser(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
ArraySet<String> simpleNames = new ArraySet<String>();
for (AgentInfo info : mActiveAgents) {
if (info.userId != user.id) { continue; }
boolean trusted = info.agent.isTrusted();
fout.print(" "); fout.println(info.component.flattenToShortString());
fout.print(" bound=" + dumpBool(info.agent.isBound()));
fout.print(", connected=" + dumpBool(info.agent.isConnected()));
fout.print(", managingTrust=" + dumpBool(info.agent.isManagingTrust()));
fout.print(", trusted=" + dumpBool(trusted));
fout.println();
if (trusted) {
fout.println(" message=\"" + info.agent.getMessage() + "\"");
}
if (!info.agent.isConnected()) {
String restartTime = TrustArchive.formatDuration(
info.agent.getScheduledRestartUptimeMillis()
- SystemClock.uptimeMillis());
fout.println(" restartScheduledAt=" + restartTime);
}
if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
duplicateSimpleNames = true;
}
}
fout.println(" Events:");
mArchive.dump(fout, 50, user.id, " " /* linePrefix */, duplicateSimpleNames);
fout.println();
} private String dumpBool(boolean b) {
return b ? "1" : "0";
} private String dumpHex(int i) {
return "0x" + Integer.toHexString(i);
} @Override
public void setDeviceLockedForUser(int userId, boolean locked) {
enforceReportPermission();
final long identity = Binder.clearCallingIdentity();
try {
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
synchronized (mDeviceLockedForUser) {
mDeviceLockedForUser.put(userId, locked);
}
if (locked) {
try {
ActivityManager.getService().notifyLockedProfile(userId);
} catch (RemoteException e) {
}
}
final Intent lockIntent = new Intent(Intent.ACTION_DEVICE_LOCKED_CHANGED);
lockIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
lockIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mContext.sendBroadcastAsUser(lockIntent, UserHandle.SYSTEM,
Manifest.permission.TRUST_LISTENER, /* options */ null);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
} @Override
public boolean isTrustUsuallyManaged(int userId) {
mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
"query trust state");
return isTrustUsuallyManagedInternal(userId);
} @Override
public void unlockedByFingerprintForUser(int userId) {
enforceReportPermission();
synchronized(mUsersUnlockedByFingerprint) {
mUsersUnlockedByFingerprint.put(userId, true);
}
mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, userId,
0 /* arg2 */).sendToTarget();
} @Override
public void clearAllFingerprints() {
enforceReportPermission();
synchronized(mUsersUnlockedByFingerprint) {
mUsersUnlockedByFingerprint.clear();
}
mHandler.obtainMessage(MSG_REFRESH_DEVICE_LOCKED_FOR_USER, UserHandle.USER_ALL,
0 /* arg2 */).sendToTarget();
}
}; private boolean isTrustUsuallyManagedInternal(int userId) {
synchronized (mTrustUsuallyManagedForUser) {
int i = mTrustUsuallyManagedForUser.indexOfKey(userId);
if (i >= 0) {
return mTrustUsuallyManagedForUser.valueAt(i);
}
}
// It's not in memory yet, get the value from persisted storage instead
boolean persistedValue = mLockPatternUtils.isTrustUsuallyManaged(userId);
synchronized (mTrustUsuallyManagedForUser) {
int i = mTrustUsuallyManagedForUser.indexOfKey(userId);
if (i >= 0) {
// Someone set the trust usually managed in the mean time. Better use that.
return mTrustUsuallyManagedForUser.valueAt(i);
} else {
// .. otherwise it's safe to cache the fetched value now.
mTrustUsuallyManagedForUser.put(userId, persistedValue);
return persistedValue;
}
}
} private int resolveProfileParent(int userId) {
long identity = Binder.clearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(userId);
if (parent != null) {
return parent.getUserHandle().getIdentifier();
}
return userId;
} finally {
Binder.restoreCallingIdentity(identity);
}
} private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_LISTENER:
addListener((ITrustListener) msg.obj);
break;
case MSG_UNREGISTER_LISTENER:
removeListener((ITrustListener) msg.obj);
break;
case MSG_DISPATCH_UNLOCK_ATTEMPT:
dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
break;
case MSG_DISPATCH_UNLOCK_LOCKOUT:
dispatchUnlockLockout(msg.arg1, msg.arg2);
break;
case MSG_ENABLED_AGENTS_CHANGED:
refreshAgentList(UserHandle.USER_ALL);
// This is also called when the security mode of a user changes.
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_KEYGUARD_SHOWING_CHANGED:
refreshDeviceLockedForUser(mCurrentUser);
break;
case MSG_START_USER:
case MSG_CLEANUP_USER:
case MSG_UNLOCK_USER:
refreshAgentList(msg.arg1);
break;
case MSG_SWITCH_USER:
mCurrentUser = msg.arg1;
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_STOP_USER:
setDeviceLockedForUser(msg.arg1, true);
break;
case MSG_FLUSH_TRUST_USUALLY_MANAGED:
SparseBooleanArray usuallyManaged;
synchronized (mTrustUsuallyManagedForUser) {
usuallyManaged = mTrustUsuallyManagedForUser.clone();
} for (int i = 0; i < usuallyManaged.size(); i++) {
int userId = usuallyManaged.keyAt(i);
boolean value = usuallyManaged.valueAt(i);
if (value != mLockPatternUtils.isTrustUsuallyManaged(userId)) {
mLockPatternUtils.setTrustUsuallyManaged(value, userId);
}
}
break;
case MSG_REFRESH_DEVICE_LOCKED_FOR_USER:
refreshDeviceLockedForUser(msg.arg1);
break;
}
}
}; private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
public void onSomePackagesChanged() {
refreshAgentList(UserHandle.USER_ALL);
} @Override
public boolean onPackageChanged(String packageName, int uid, String[] components) {
// We're interested in all changes, even if just some components get enabled / disabled.
return true;
} @Override
public void onPackageDisappeared(String packageName, int reason) {
removeAgentsOfPackage(packageName);
}
}; 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
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
refreshAgentList(getSendingUserId());
updateDevicePolicyFeatures();
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
maybeEnableFactoryTrustAgents(mLockPatternUtils, userId);
}
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
int userId = getUserId(intent);
if (userId > 0) {
synchronized (mUserIsTrusted) {
mUserIsTrusted.delete(userId);
}
synchronized (mDeviceLockedForUser) {
mDeviceLockedForUser.delete(userId);
}
synchronized (mTrustUsuallyManagedForUser) {
mTrustUsuallyManagedForUser.delete(userId);
}
synchronized (mUsersUnlockedByFingerprint) {
mUsersUnlockedByFingerprint.delete(userId);
}
refreshAgentList(userId);
refreshDeviceLockedForUser(userId);
}
}
} private int getUserId(Intent intent) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100);
if (userId > 0) {
return userId;
} else {
Slog.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId);
return -100;
}
} public void register(Context context) {
IntentFilter filter = new IntentFilter();
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_REMOVED);
context.registerReceiverAsUser(this,
UserHandle.ALL,
filter,
null /* permission */,
null /* scheduler */);
}
} private class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { SparseBooleanArray mStartFromSuccessfulUnlock = new SparseBooleanArray(); public StrongAuthTracker(Context context) {
super(context);
} @Override
public void onStrongAuthRequiredChanged(int userId) {
mStartFromSuccessfulUnlock.delete(userId); if (DEBUG) {
Log.i(TAG, "onStrongAuthRequiredChanged(" + userId + ") ->"
+ " trustAllowed=" + isTrustAllowedForUser(userId)
+ " agentsCanRun=" + canAgentsRunForUser(userId));
} refreshAgentList(userId); // The list of active trust agents may not have changed, if there was a previous call
// to allowTrustFromUnlock, so we update the trust here too.
updateTrust(userId, 0 /* flags */);
} boolean canAgentsRunForUser(int userId) {
return mStartFromSuccessfulUnlock.get(userId)
|| super.isTrustAllowedForUser(userId);
} /**
* Temporarily suppress strong auth requirements for {@param userId} until strong auth
* changes again. Must only be called when we know about a successful unlock already
* before the underlying StrongAuthTracker.
*
* Note that this only changes whether trust agents can be started, not the actual trusted
* value.
*/
void allowTrustFromUnlock(int userId) {
if (userId < UserHandle.USER_SYSTEM) {
throw new IllegalArgumentException("userId must be a valid user: " + userId);
}
boolean previous = canAgentsRunForUser(userId);
mStartFromSuccessfulUnlock.put(userId, true); if (DEBUG) {
Log.i(TAG, "allowTrustFromUnlock(" + userId + ") ->"
+ " trustAllowed=" + isTrustAllowedForUser(userId)
+ " agentsCanRun=" + canAgentsRunForUser(userId));
} if (canAgentsRunForUser(userId) != previous) {
refreshAgentList(userId);
}
}
}
}

TrustManagerService.java的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. 故障重现&lpar;内存篇2&rpar;,JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  3. Elasticsearch之java的基本操作一

    摘要   接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...

  4. 论:开发者信仰之&OpenCurlyDoubleQuote;天下IT是一家&OpenCurlyDoubleQuote;&lpar;Java &period;NET篇&rpar;

    比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...

  5. 故障重现&comma; JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

  6. 死磕内存篇 --- JAVA进程和linux内存间的大小关系

    运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...

  7. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

  8. Java多线程基础学习(二)

    9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...

  9. Java多线程基础学习(一)

    1. 创建线程    1.1 通过构造函数:public Thread(Runnable target, String name){}  或:public Thread(Runnable target ...

随机推荐

  1. SpringBoot IntelliJ创建简单的Restful接口

    使用SpringBoot快速建服务,和NodeJS使用express几乎一模一样,主要分为以下: 1.添加和安装依赖  2.添加路由(即接口) 3.对路由事件进行处理 同样坑的地方就是,祖国的防火墙太 ...

  2. putty&plus;xming远程登录Ubuntu16&period;04图形界面

    前面我写过一篇<Ubuntu16.04 安装ftp服务器传输文件>的文章.文章当中已经可以远程访问linux服务器并且传输文件,然而要在putty中使用开启图形界面的命令到目前为止还是不够 ...

  3. YYModel 源码历险记 代码结构

    前言 因为公司需要开发一个内部使用的字典转模型的项目,所以最近也是在看关于字典转模型的内容.有Mantle,jsonModel,MJExtension等众多框架,最后还是选择了先从YYModel源码读 ...

  4. 修改本地配置远程连接oracle数据库

    当我们需要查看数据库信息时,我们更愿意通过客户端来查看,这样不仅操作方便,而且查看更精准.那么需要远程连接数据库需要在本地修改那些配置呢?以下是我个人的经验,希望大家都指正. 1.在oracle安装目 ...

  5. &lbrack;51nod1457&rsqb;小K vs&period; 竹子

    小K的花园种着n颗竹子(竹子是一种茎部中空并且长得又高又快的热带植物).此时,花园中第i颗竹子的高度是hi米,并且在每天结束的时候它生长ai米. 实际上,小K十分讨厌这些竹子.他曾经试图去砍光它们,但 ...

  6. &lbrack;物理学与PDEs&rsqb;第4章习题4 一维理想反应流体力学方程组的守恒律形式及其 R&period;H&period; 条件

    写出在忽略粘性与热传导性, 即设 $\mu=\mu'=\kappa=0$ 的情况, 在 Euler 坐标系下具守恒律形式的一维反应流动力学方程组. 由此求出在解的强间断线上应满足的 R.H. 条件 ( ...

  7. python连接mysql实例分享&lowbar;python

    示例一 #coding=UTF-8 import sys import MySQLdb import time reload(sys) sys.setdefaultencoding('utf-8') ...

  8. IT小小鸟 读书笔记

    讲真的,整本书我并没有看完,翻阅了一下,然后小小的借鉴了一下! 首先设计你自己的进度条 进度条的设计是一个很多人都知道的故事:同样的耗时,如果不给任何进度提示,只是在完成之后才弹出一个完成消息,中间没 ...

  9. MyEclipse------如何添加jspsmartupload&period;jar,用于文件上传

    方法: 右键“Web”工程->properties->Libraries->Add External JARs...->找到“jspsmartupload.jar”,添加进去 ...

  10. 线程队列之阻塞队列LinkedBlockingQueue

    在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出).Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQ ...