Detailed explanation of the method of prohibiting the installation and uninstallation of third party apk by android

  • 2021-12-11 08:45:34
  • OfStack

The requirement is that the customer requires to provide the system interface to control the installation and uninstallation of apk, and the interface is as follows


boolean setAppInstallationPolicies(int mode, String[] appPackageNames)
mode Apply list type 
0 Blacklist ( All items in the application package name list are not allowed to install ) ; 
1 White list ( Only items in the application package name list are allowed to be installed ) . 
appPackageNames Apply package name list. When appPackageNames When it is empty, cancel all configured applications. 
 Successful return true ; Failure return false . 
String[] getAppInstallationPolicies()
 The return value is the current application installation control status 
string[0] : Functional mode, see setAppInstallationPolicies Method's mode Parameter. 
string[1] To string[n-1] Apply package name list. 
 
 
boolean setAppUninstallationPolicies(int mode, String[] appPackageNames)
mode Apply list type 
0 Blacklist ( All items in the application package name list are forced to uninstall ) ; 
1 White list ( Apply all items in the package name list to prohibit uninstallation ) . 
appPackageNames Apply package name list. When appPackageNames When it is empty, cancel all configured applications. 
 Successful return true ; Failure return false . 
String[] getAppUninstallationPolicies()
 The return value is the current application unloading control status 
string[0] : Functional mode, see setAppUninstallationPolicies Method's mode Parameter. 
string[1] To string[n-1] Apply package name list. 

The version of android is 9.0. The first thought is to add one service to the system, and add IPolicyManager. aidl, frameworks/base/services/core/java/com/android/server/PolicyManagerService. java, frameworks/base/policy/java/ga/mdm/PolicyManager. java respectively. The contents are as follows


package android.app;
 
/** {@hide} */
interface IPolicyManager
{
	
	boolean setAppInstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppInstallationPolicies();
	
	boolean setAppUninstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppUninstallationPolicies();
	
}

package com.android.server;
 
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
 
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Slog;
 
import java.lang.reflect.Field;
import java.util.ArrayList;
 
import android.app.IPolicyManager;
import android.net.wifi.WifiManager;
import android.content.pm.PackageManager;
import android.app.ActivityManager;
import android.content.pm.IPackageDataObserver;
 
public class PolicyManagerService extends IPolicyManager.Stub {
	
	private final String TAG = "PolicyManagerService";
	private Context mContext;
	
	private String[] mAppPackageNames = null;
	
	private String[] mAppUninstallPackageNames = null;
	
	
 public PolicyManagerService(Context context) {
  mContext = context;
 
 }
	
	@Override
	public boolean setAppInstallationPolicies(int mode, String[] appPackageNames){
		if(mode==0){
			Settings.System.putInt(mContext.getContentResolver(),"customer_app_status", 0);	
		}else if(mode==1){
			Settings.System.putInt(mContext.getContentResolver(),"customer_app_status", 1);	
		}else{
			return false;
		}
		mAppPackageNames = appPackageNames;
		return true;
	}
	
	@Override
	public String[] getAppInstallationPolicies(){
		return mAppPackageNames;
	}
	@Override
	public boolean setAppUninstallationPolicies(int mode,String[] appPackageNames){
		if(mode==0){
			Settings.System.putInt(mContext.getContentResolver(),"customer_appuninstall_status", 0);	
		}else if(mode==1){
			Settings.System.putInt(mContext.getContentResolver(),"customer_appuninstall_status", 1);	
		}else{
			return false;
		}
		mAppUninstallPackageNames = appPackageNames;
		return true;
	}
	@Override
	public String[] getAppUninstallationPolicies(){
		return mAppUninstallPackageNames;
	}
}

package ga.mdm;
 
import android.util.Slog;
import android.os.RemoteException;
import android.content.Context;
import android.app.IPolicyManager;
 
public class PolicyManager {
	private final String TAG = "PolicyManager";
	Context mContext;
 
 private final IPolicyManager mService;
 
 public PolicyManager(Context context,IPolicyManager mService) {
		mContext = context;
  this.mService = mService;
 }
 
	
	public boolean setAppInstallationPolicies(int mode,String[] appPackageNames){
		try { 
			return mService.setAppInstallationPolicies(mode,appPackageNames);
  } catch (RemoteException ex) {
   ex.printStackTrace();
			return false;
  } 
	}
	
	public String[] getAppInstallationPolicies(){
		try { 
			return mService.getAppInstallationPolicies();
  } catch (RemoteException ex) {
   ex.printStackTrace();
			return null;
  } 
	}
	
	public boolean setAppUninstallationPolicies(int mode,String[] appPackageNames){
		try { 
			return mService.setAppUninstallationPolicies(mode,appPackageNames);
  } catch (RemoteException ex) {
   ex.printStackTrace();
			return false;
  } 
	}
	
	public String[] getAppUninstallationPolicies(){
		try { 
			return mService.getAppUninstallationPolicies();
  } catch (RemoteException ex) {
   ex.printStackTrace();
			return null;
  } 
	}
	
}

Add Android. mk to frameworks/base/policy/frameworks/mk


# 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.
 
LOCAL_PATH := $(call my-dir)
 
# Build the java code
# ============================================================
 
include $(CLEAR_VARS)
 
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/java
LOCAL_SRC_FILES := $(call all-java-files-under, java) \
	$(call all-Iaidl-files-under, java) \
	$(call all-logtags-files-under, java)
 
LOCAL_JAVA_LIBRARIES := services
LOCAL_MODULE := policy
 
include $(BUILD_JAVA_LIBRARY)
 
include $(call all-makefiles-under,$(LOCAL_PATH))

Why does PolicyManager. java come out separately here, because PolicyManager. java is provided to customers, and one jar package is generated separately. Customers only need to use policy. jar to call and need to add at the same time


--- frameworks/base/Android.bp	(revision 221)
+++ frameworks/base/Android.bp	(working copy)
@@ -46,7 +46,8 @@
     "wifi/java/**/*.java",
     "keystore/java/**/*.java",
     "rs/java/**/*.java",
-
+		"policy/java/**/*.java",
+	
     ":framework-javastream-protos",
 
     "core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl",
@@ -105,6 +106,7 @@
     "core/java/android/app/usage/ICacheQuotaService.aidl",
     "core/java/android/app/usage/IStorageStatsManager.aidl",
     "core/java/android/app/usage/IUsageStatsManager.aidl",
+		"core/java/android/app/IPolicyManager.aidl",
     ":libbluetooth-binder-aidl",
     "core/java/android/content/IClipboard.aidl",
     "core/java/android/content/IContentService.aidl",

Add the path to, otherwise it will not compile


-- build/make/core/pathmap.mk	(revision 221)
+++ build/make/core/pathmap.mk	(working copy)
@@ -83,6 +83,7 @@
 	  lowpan \
 	  keystore \
 	  rs \
+		policy \
 	 )

Add Module


--- build/make/target/product/base.mk	(revision 221)
+++ build/make/target/product/base.mk	(working copy)
@@ -142,7 +142,8 @@
   traced_probes \
   vdc \
   vold \
-  wm
+  wm \
+	policy

Add the code to register the service


--- frameworks/base/core/java/android/content/Context.java	(revision 221)
+++ frameworks/base/core/java/android/content/Context.java	(working copy)
@@ -4198,6 +4198,9 @@
   * @see #getSystemService(String)
   */
   public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
+	
+	
+	public static final String POLICY_SERVICE = "policy";

+import ga.mdm.PolicyManager;
+
 /**
 * Manages all of the system services that can be returned by {@link Context#getSystemService}.
 * Used by {@link ContextImpl}.
@@ -982,6 +984,15 @@
         return new VrManager(IVrManager.Stub.asInterface(b));
       }
     });
+		
+		registerService(Context.POLICY_SERVICE, PolicyManager.class,
+        new CachedServiceFetcher<PolicyManager>() {
+      @Override
+      public PolicyManager createService(ContextImpl ctx) {
+        IBinder b = ServiceManager.getService(Context.POLICY_SERVICE);
+        IPolicyManager service = IPolicyManager.Stub.asInterface(b);
+        return new PolicyManager(ctx, service);
+    }});

package android.app;
 
/** {@hide} */
interface IPolicyManager
{
	
	boolean setAppInstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppInstallationPolicies();
	
	boolean setAppUninstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppUninstallationPolicies();
	
}
0

You also need to add selinux permissions


package android.app;
 
/** {@hide} */
interface IPolicyManager
{
	
	boolean setAppInstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppInstallationPolicies();
	
	boolean setAppUninstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppUninstallationPolicies();
	
}
1

That's it. You can see the added service by rebooting the burn and using adb shell service list


package android.app;
 
/** {@hide} */
interface IPolicyManager
{
	
	boolean setAppInstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppInstallationPolicies();
	
	boolean setAppUninstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppUninstallationPolicies();
	
}
2

Find classes. jar in\ out\ target\ common\ obj\ JAVA_LIBRARIES\ policy_intermediates, which is the jar provided to customers

The specific prohibition and uninstallation methods are as follows:

To disable installation, you can modify PackageManagerService. java by adding the following code to the handleStartCopy method


public void handleStartCopy() throws RemoteException {
      int ret = PackageManager.INSTALL_SUCCEEDED;
 
      // If we're already staged, we've firmly committed to an install location
      if (origin.staged) {
        if (origin.file != null) {
          installFlags |= PackageManager.INSTALL_INTERNAL;
          installFlags &= ~PackageManager.INSTALL_EXTERNAL;
        } else {
          throw new IllegalStateException("Invalid stage location");
        }
      }
 
      final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
      final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
      final boolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
      PackageInfoLite pkgLite = null;
 
      if (onInt && onSd) {
        // Check if both bits are set.
        Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
      } else if (onSd && ephemeral) {
        Slog.w(TAG, "Conflicting flags specified for installing ephemeral on external");
        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
      } else {
        pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
            packageAbiOverride);
				
				//add by jueme
				PolicyManager policyManager = (PolicyManager)mContext.getSystemService("policy");
				String[] appNames = policyManager.getAppInstallationPolicies();
				if(appNames!=null && appNames.length>0){
					int app_status = android.provider.Settings.System.getInt(mContext.getContentResolver(),"customer_app_status", -1);
					Slog.w(TAG,"app_status "+app_status);
					if(app_status==0){
						for (int i = 0; i < appNames.length; i++) {
							Slog.w(TAG,"appNames 0 "+appNames[i]);
							if (pkgLite.packageName.equals(appNames[i])){
								ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
								break;
							}
						}
					}else if(app_status==1){
						for (int i = 0; i < appNames.length; i++) {
							Slog.w(TAG,"appNames 1 "+appNames[i]);
							if (pkgLite.packageName.equals(appNames[i])){
								ret = PackageManager.INSTALL_SUCCEEDED;
								break;
							}else{
								ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
							}
						}
					}
				}
				//add end

In this way, the information that the installation position is wrong will be reported during installation.

Next, disable uninstall, adding the following method to uninstall of PackageInstallerService. java.


package android.app;
 
/** {@hide} */
interface IPolicyManager
{
	
	boolean setAppInstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppInstallationPolicies();
	
	boolean setAppUninstallationPolicies(int mode,inout String[] appPackageNames);
	
	String[] getAppUninstallationPolicies();
	
}
4

Related articles: