需求:控制应用启动,蓝牙开启,USB切MTP模式
原理:设置里面定义一个PrizeCheckPasswordActivity.java用于验证密码,修改密码,定义一个receiver用于从系统服务中发广播启动Activity.系统服务中不能直接启动PrizeCheckPasswordActivity,否则会报权限问题。
应用密码控制关键代码:
frameworks/base/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
}
if (interceptHarmfulAppIfNeeded()) {
// If the app has a "harmful app" warning associated with it, we should ask to uninstall
// before issuing the work challenge.
return true;
}
final int app_type = appShouldCheckPasswordOrNot();
if(app_type != -1){
android.util.Log.e("PasswordService","appShouldCheckPasswordOrNot true");
if(interceptShouldCheckPasswordAppIfNeeded(app_type)){
android.util.Log.e("PasswordService","interceptShouldCheckPasswordAppIfNeeded true not start origin app");
return true;
}
}
return interceptLockedManagedProfileIfNeeded();
}
.....
private int appShouldCheckPasswordOrNot(){
final int PASSWORD_ID_HUAWEIMARKET = 4;
final int PASSWORD_ID_BROWSER = 8;
if("com.android.browser".equals(mAInfo.packageName))
return PASSWORD_ID_BROWSER;
if("com.huawei.appmarket".equals(mAInfo.packageName))
return PASSWORD_ID_HUAWEIMARKET;
return -1;
}
private boolean interceptShouldCheckPasswordAppIfNeeded(int type) {
PasswordManager passwordManager = (PasswordManager) mServiceContext
.getSystemService("password");
if(!passwordManager.checkPasswordStatus(type)){
final IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT | FLAG_IMMUTABLE);
mIntent = new Intent("com.prize.password.action.CHECK_PASSWORD");
mIntent.putExtra("check_type", type);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mCallingPid = mRealCallingPid;
mCallingUid = mRealCallingUid;
mResolvedType = null;
mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, 0, mRealCallingUid);
mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
return true;
}else{
return false;
}
}
蓝牙控制:
./core/java/com/android/server/BluetoothManagerService.java
private final int PASSWORD_ID_BLUETOOTH = 1;
private boolean sendPrizeCheckPasswordBroadcastIfPasswordWasWrong(int type){
int status = android.provider.Settings.Secure.getInt(mContext.getContentResolver(), "status_key", 0);
android.util.Log.i(TAG,"BMS sendPrizeCheckPasswordBroadcastIfPasswordWasWrong status saved =" + status +",type=" + type);
if((type & status) != 0){//password right
return false;
}else{
final String CHECK_PASSWORD_ACTION = "com.prize.password.action.CHECK_PASSWORD_STATUS";
ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.password.PrizeCheckPasswordReceiver");
Intent intent = new Intent();
intent.setComponent(cn);
intent.setAction(CHECK_PASSWORD_ACTION);
intent.putExtra("check_type", type);
mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
return true;
}
}
public boolean enable(String packageName) throws RemoteException {
if(sendPrizeCheckPasswordBroadcastIfPasswordWasWrong(PASSWORD_ID_BLUETOOTH)){
Slog.d(TAG, "PasswordService password is wrong,just return");
return false;
}
if (!checkBluetoothPermissions(packageName, true)) {
if (DBG) {
Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
}
return false;
}
USB切MTP模式控制:
./frameworks/base/services/usb/java/com/android/server/usb/UsbService.java
private final int PASSWORD_ID_USB = 2;
private boolean sendPrizeCheckPasswordBroadcastIfPasswordWasWrong(int type){
int status = android.provider.Settings.Secure.getInt(mContext.getContentResolver(), "status_key", 0);
android.util.Log.i("PasswordService","BMS appShouldinterceptOrNot status saved =" + status +",type=" + type);
if((type & status) != 0){//password right
return false;
}else{
final String CHECK_PASSWORD_ACTION = "com.prize.password.action.CHECK_PASSWORD_STATUS";
ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.password.PrizeCheckPasswordReceiver");
Intent intent = new Intent();
intent.setComponent(cn);
intent.setAction(CHECK_PASSWORD_ACTION);
intent.putExtra("check_type", type);
mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
return true;
}
}
@Override
public void setCurrentFunctions(long functions) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
Preconditions.checkArgument(UsbManager.areSettableFunctions(functions));
Preconditions.checkState(mDeviceManager != null);
if(functions == UsbManager.FUNCTION_MTP && sendPrizeCheckPasswordBroadcastIfPasswordWasWrong(PASSWORD_ID_USB)){
android.util.Log.e("PasswordService", "UsbService password is wrong just return");
return;
}
mDeviceManager.setCurrentFunctions(functions);
}
设置里面的Manifest配置:
dialog样式:
注意系统服务发广播的方式,不然由于receiver是在AndroidManifest.xml中静态注册的,很可能会收不到。