记一次密码控制功能

需求:控制应用启动,蓝牙开启,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中静态注册的,很可能会收不到。

你可能感兴趣的:(Android系统功能开发,android,java)