android 禁止第三方apk android 禁止第三方apk安装和卸载的方法详解
jueme 人气:0需求是这样的,客户要求提供系统的接口来控制apk的安装和卸载,接口如下
boolean setAppInstallationPolicies(int mode, String[] appPackageNames) mode:应用名单类型 0:黑名单(应用包名列表中的所有项都不允许安装); 1:白名单(只允许安装应用包名列表中的项)。 appPackageNames:应用包名列表。当appPackageNames为空时,取消所有已设定的应用。 成功返回true;失败返回false。 String[] getAppInstallationPolicies() 返回值为当前应用安装管控状态 string[0]:功能模式,参见setAppInstallationPolicies方法的mode参数。 string[1]至string[n-1]:应用包名列表。 boolean setAppUninstallationPolicies(int mode, String[] appPackageNames) mode:应用名单类型 0:黑名单(应用包名列表中的所有项均强制卸载); 1:白名单(应用包名列表中的所有项禁止卸载)。 appPackageNames:应用包名列表。当appPackageNames为空时,取消所有已设定的应用。 成功返回true;失败返回false。 String[] getAppUninstallationPolicies() 返回值为当前应用卸载管控状态 string[0]:功能模式,参见setAppUninstallationPolicies方法的mode参数。 string[1]至string[n-1]:应用包名列表。
android版本为9.0,首先想到的是在系统里面添加一个自己的service,分别在frameworks/base/core/java/android/app/添加IPolicyManager.aidl,frameworks/base/services/core/java/com/android/server/添加PolicyManagerService.java,在frameworks/base/添加policy/java/ga/mdm/PolicyManager.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(); }
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; } } }
同时在frameworks/base/policy/添加Android.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))
这里为什么将PolicyManager.java单独出来,因为PolicyManager.java是提供给客户用的,单独生成一个jar包,客户只需要使用policy.jar就可以调用,同时需要添加
--- 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",
将路径添加到,否则不会编译
-- build/make/core/pathmap.mk (revision 221) +++ build/make/core/pathmap.mk (working copy) @@ -83,6 +83,7 @@ lowpan \ keystore \ rs \ + policy \ )
添加模块
--- 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
添加注册服务的代码
--- 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); + }});
+import com.android.server.PolicyManagerService; + public final class SystemServer { private static final String TAG = "SystemServer"; @@ -1287,7 +1289,14 @@ } traceEnd(); } - + + try { + Slog.i(TAG, "ClassMonitor Service is create"); + ServiceManager.addService(Context.POLICY_SERVICE, new PolicyManagerService(context)); + } catch (Throwable e) { + reportWtf("starting ClassMonitorService", e); + }
还需要添加selinux权限
--- system/sepolicy/Android.mk (revision 221) +++ system/sepolicy/Android.mk (working copy) @@ -244,10 +244,10 @@ ifneq ($(with_asan),true) ifneq ($(SELINUX_IGNORE_NEVERALLOWS),true) -LOCAL_REQUIRED_MODULES += \ - sepolicy_tests \ - treble_sepolicy_tests_26.0 \ - treble_sepolicy_tests_27.0 \ +#LOCAL_REQUIRED_MODULES += \ +# sepolicy_tests \ +# treble_sepolicy_tests_26.0 \ +# treble_sepolicy_tests_27.0 \ endif endif Index: system/sepolicy/prebuilts/api/26.0/nonplat_sepolicy.cil =================================================================== --- system/sepolicy/prebuilts/api/26.0/nonplat_sepolicy.cil (revision 221) +++ system/sepolicy/prebuilts/api/26.0/nonplat_sepolicy.cil (working copy) @@ -135,6 +135,8 @@ (typeattributeset hal_wifi_supplicant_server (hal_wifi_supplicant_default)) (typeattribute adbd_26_0) (roletype object_r adbd_26_0) +(typeattribute policy_service_26_0) +(roletype object_r policy_service_26_0) (typeattribute audioserver_26_0) (roletype object_r audioserver_26_0) (typeattribute blkid_26_0) Index: system/sepolicy/prebuilts/api/27.0/nonplat_sepolicy.cil =================================================================== --- system/sepolicy/prebuilts/api/27.0/nonplat_sepolicy.cil (revision 221) +++ system/sepolicy/prebuilts/api/27.0/nonplat_sepolicy.cil (working copy) @@ -267,6 +267,8 @@ (typeattributeset hal_wifi_supplicant_server (hal_wifi_supplicant_default)) (typeattribute adbd_27_0) (roletype object_r adbd_27_0) +(typeattribute policy_service_26_0) +(roletype object_r policy_service_26_0) (typeattribute adbd_exec_27_0) (roletype object_r adbd_exec_27_0) (typeattribute audioserver_27_0) Index: system/sepolicy/prebuilts/api/28.0/private/app_neverallows.te =================================================================== --- system/sepolicy/prebuilts/api/28.0/private/app_neverallows.te (revision 221) +++ system/sepolicy/prebuilts/api/28.0/private/app_neverallows.te (working copy) @@ -128,7 +128,6 @@ proc_stat proc_swaps proc_uptime - proc_version proc_vmallocinfo proc_vmstat }:file { no_rw_file_perms no_x_file_perms }; Index: system/sepolicy/prebuilts/api/28.0/private/compat/26.0/26.0.cil =================================================================== --- system/sepolicy/prebuilts/api/28.0/private/compat/26.0/26.0.cil (revision 221) +++ system/sepolicy/prebuilts/api/28.0/private/compat/26.0/26.0.cil (working copy) @@ -15,6 +15,7 @@ (type rild) (typeattributeset accessibility_service_26_0 (accessibility_service)) +(typeattributeset policy_service_26_0 (policy_service)) (typeattributeset account_service_26_0 (account_service)) (typeattributeset activity_service_26_0 (activity_service)) (typeattributeset adbd_26_0 (adbd)) Index: system/sepolicy/prebuilts/api/28.0/private/compat/27.0/27.0.cil =================================================================== --- system/sepolicy/prebuilts/api/28.0/private/compat/27.0/27.0.cil (revision 221) +++ system/sepolicy/prebuilts/api/28.0/private/compat/27.0/27.0.cil (working copy) @@ -718,6 +718,7 @@ (expandtypeattribute (zygote_exec_27_0) true) (expandtypeattribute (zygote_socket_27_0) true) (typeattributeset accessibility_service_27_0 (accessibility_service)) +(typeattributeset policy_service_27_0 (policy_service)) (typeattributeset account_service_27_0 (account_service)) (typeattributeset activity_service_27_0 (activity_service)) (typeattributeset adbd_27_0 (adbd)) Index: system/sepolicy/prebuilts/api/28.0/private/service_contexts =================================================================== --- system/sepolicy/prebuilts/api/28.0/private/service_contexts (revision 221) +++ system/sepolicy/prebuilts/api/28.0/private/service_contexts (working copy) @@ -186,3 +186,4 @@ wifirtt u:object_r:rttmanager_service:s0 window u:object_r:window_service:s0 * u:object_r:default_android_service:s0 +policy u:object_r:policy_service:s0 Index: system/sepolicy/prebuilts/api/28.0/private/system_server.te =================================================================== --- system/sepolicy/prebuilts/api/28.0/private/system_server.te (revision 221) +++ system/sepolicy/prebuilts/api/28.0/private/system_server.te (working copy) @@ -806,7 +806,7 @@ # Do not allow opening files from external storage as unsafe ejection # could cause the kernel to kill the system_server. neverallow system_server sdcard_type:dir { open read write }; -neverallow system_server sdcard_type:file rw_file_perms; +# neverallow system_server sdcard_type:file rw_file_perms; # system server should never be operating on zygote spawned app data # files directly. Rather, they should always be passed via a Index: system/sepolicy/prebuilts/api/28.0/public/service.te =================================================================== --- system/sepolicy/prebuilts/api/28.0/public/service.te (revision 221) +++ system/sepolicy/prebuilts/api/28.0/public/service.te (working copy) @@ -32,6 +32,7 @@ type virtual_touchpad_service, service_manager_type; type vold_service, service_manager_type; type vr_hwc_service, service_manager_type; +type policy_service, system_api_service, system_server_service, service_manager_type; # system_server_services broken down type accessibility_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type; Index: system/sepolicy/private/app_neverallows.te =================================================================== --- system/sepolicy/private/app_neverallows.te (revision 221) +++ system/sepolicy/private/app_neverallows.te (working copy) @@ -128,7 +128,6 @@ proc_stat proc_swaps proc_uptime - proc_version proc_vmallocinfo proc_vmstat }:file { no_rw_file_perms no_x_file_perms }; Index: system/sepolicy/private/compat/26.0/26.0.cil =================================================================== --- system/sepolicy/private/compat/26.0/26.0.cil (revision 221) +++ system/sepolicy/private/compat/26.0/26.0.cil (working copy) @@ -15,6 +15,7 @@ (type rild) (typeattributeset accessibility_service_26_0 (accessibility_service)) +(typeattributeset policy_service_26_0 (policy_service)) (typeattributeset account_service_26_0 (account_service)) (typeattributeset activity_service_26_0 (activity_service)) (typeattributeset adbd_26_0 (adbd)) Index: system/sepolicy/private/compat/27.0/27.0.cil =================================================================== --- system/sepolicy/private/compat/27.0/27.0.cil (revision 221) +++ system/sepolicy/private/compat/27.0/27.0.cil (working copy) @@ -718,6 +718,7 @@ (expandtypeattribute (zygote_exec_27_0) true) (expandtypeattribute (zygote_socket_27_0) true) (typeattributeset accessibility_service_27_0 (accessibility_service)) +(typeattributeset policy_service_27_0 (policy_service)) (typeattributeset account_service_27_0 (account_service)) (typeattributeset activity_service_27_0 (activity_service)) (typeattributeset adbd_27_0 (adbd)) Index: system/sepolicy/private/service_contexts =================================================================== --- system/sepolicy/private/service_contexts (revision 221) +++ system/sepolicy/private/service_contexts (working copy) @@ -186,3 +186,4 @@ wifirtt u:object_r:rttmanager_service:s0 window u:object_r:window_service:s0 * u:object_r:default_android_service:s0 +policy u:object_r:policy_service:s0 Index: system/sepolicy/private/system_server.te =================================================================== --- system/sepolicy/private/system_server.te (revision 221) +++ system/sepolicy/private/system_server.te (working copy) @@ -806,7 +806,7 @@ # Do not allow opening files from external storage as unsafe ejection # could cause the kernel to kill the system_server. neverallow system_server sdcard_type:dir { open read write }; -neverallow system_server sdcard_type:file rw_file_perms; +# neverallow system_server sdcard_type:file rw_file_perms; # system server should never be operating on zygote spawned app data # files directly. Rather, they should always be passed via a Index: system/sepolicy/public/service.te =================================================================== --- system/sepolicy/public/service.te (revision 221) +++ system/sepolicy/public/service.te (working copy) @@ -32,6 +32,7 @@ type virtual_touchpad_service, service_manager_type; type vold_service, service_manager_type; type vr_hwc_service, service_manager_type; +type policy_service, system_api_service, system_server_service, service_manager_type; # system_server_services broken down type accessibility_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
这样就行了,烧录重新开机使用adb shell service list可以看到添加的service
policy: [android.app.IPolicyManager]
在\out\target\common\obj\JAVA_LIBRARIES\policy_intermediates找到classes.jar,这就是提供给客户用的jar
具体的禁止和卸载方法如下:
禁止安装可以修改PackageManagerService.java,在handleStartCopy方法中添加下面的代码
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
这样在安装时候就会报安装位置不对的信息。
接着是禁止卸载,在PackageInstallerService.java的uninstall添加下面的方法。
@Override public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags, IntentSender statusReceiver, int userId) throws RemoteException { //add by jueme PolicyManager policyManager = (PolicyManager)mContext.getSystemService("policy"); String[] appNames = policyManager.getAppUninstallationPolicies(); if(appNames!=null && appNames.length>0){ int appuninstall_status = android.provider.Settings.System.getInt(mContext.getContentResolver(),"customer_appuninstall_status", -1); Slog.w(TAG,"appuninstall_status "+appuninstall_status+" mInstallerPackageName "+versionedPackage.getPackageName()); boolean isUninstall = true;//默认都是可卸载 if(appuninstall_status==0){ for (int i = 0; i < appNames.length; i++) { if (versionedPackage.getPackageName().equals(appNames[i])){ isUninstall = true; break; }else{ isUninstall = false; } } if(!isUninstall){ return; } }else if(appuninstall_status==1){ //应用包名列表中的所有项禁止卸载 for (int i = 0; i < appNames.length; i++) { if (versionedPackage.getPackageName().equals(appNames[i])){ isUninstall = false; break; }else{ isUninstall = true; } } if(!isUninstall){ return; } } } //add end
加载全部内容