实现根据xml的packagename防止卸载,筛选安装
DataPreInstall文件夹放到vendor\tcl\sita\tvkit\uikit\frameworks\android\java\com\tcl\os\system\下
PackageManagerService.java按patch修改即可实现基本防止卸载和筛选安装功能
基本流程图
patch
+++ core/java/com/android/server/pm/PackageManagerService.java (working copy)
@@ -308,6 +308,7 @@
//Added by chyj@tcl for AppBlacklist 20170516
import com.tcl.os.system.packageverify.PackageVerify;
+import com.tcl.os.system.DataPreInstallApp.DataPreInstallApp;
//End of TCL package install strategy
@@ -346,20 +347,20 @@
*/
public class PackageManagerService extends IPackageManager.Stub {
// Debug output for dexopting. This is shared between PackageManagerService, OtaDexoptService
// and PackageDexOptimizer. All these classes have their own flag to allow switching a single
@@ -406,7 +407,7 @@
static final int SCAN_CHECK_ONLY = 1<<15;
static final int SCAN_DONT_KILL_APP = 1<<17;
static final int SCAN_IGNORE_FROZEN = 1<<18;
-
+ private boolean SCAN_DATA_APP = false; //add by chyj
static final int REMOVE_CHATTY = 1<<16;
private static final int[] EMPTY_INT_ARRAY = new int[0];
@@ -548,6 +549,7 @@
//Added by chyj @tcl for AppBlacklist 20170516
PackageVerify mPackageVerify;
+ DataPreInstallApp mDataPreInstallApp;
//End of TCL package install strategy
@@ -2129,6 +2131,7 @@
mProtectedPackages = new ProtectedPackages(mContext);
//Added by chyj@tcl for AppBlacklist 20170516
mPackageVerify = null;//new PackageVerify(); tmp delete
+ mDataPreInstallApp = new DataPreInstallApp();
//End of TCL package install strategy
synchronized (mInstallLock) {
// writer
@@ -2415,8 +2418,9 @@
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
+ SCAN_DATA_APP = true;
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
-
+ SCAN_DATA_APP = false;
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
@@ -6679,6 +6683,8 @@
// Ignore entries which are not packages
continue;
}
+ Slog.w(TAG, "chyj scanDirLI File to parse " + file );
+
try {
scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
@@ -6819,7 +6825,22 @@
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
-
+
+ if (DEBUG_INSTALL) Slog.d(TAG, "chyj scanPackageLI Parsing: scanFile=" + scanFile+" packagename="+pkg.packageName);
+ //add by chyj if is first start system and /data/app will check is preinstall frome TCL
+ if(SCAN_DATA_APP){
+ if(mDataPreInstallApp != null)
+ if(mDataPreInstallApp.verifyApp(pkg.packageName,false))
+ {
+ Log.v(TAG, "chyj package can't preinstall in Data ,delete file="+scanFile);
+ removeCodePathLI(scanFile);
+ return null;
+ }
+ else
+ Log.v(TAG, "chyj package will preinstall in data/app");
+ else
+ Log.v(TAG, "chyj mDataPreInstallApp is not init");
+ }
return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
}
@@ -15058,10 +15079,12 @@
//End of TCL
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
+
final int installFlags = args.installFlags;
final String installerPackageName = args.installerPackageName;
final String volumeUuid = args.volumeUuid;
final File tmpPackageFile = new File(args.getCodePath());
+ Slog.d(TAG,"chyj installPackageLI installerPackageName="+installerPackageName+" installFlags="+installFlags+" Path="+args.getCodePath()+" tmpPackageFile="+tmpPackageFile);
final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
|| (args.volumeUuid != null));
@@ -15144,7 +15167,7 @@
if (TextUtils.isEmpty(pkg.cpuAbiOverride)) {
pkg.cpuAbiOverride = args.abiOverride;
}
-
+ Slog.d(TAG,"chyj installPackageLI pkgName="+pkg.packageName);
String pkgName = res.name = pkg.packageName;
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
@@ -15675,7 +15698,23 @@
@Override
public void deletePackage(final String packageName,
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
- mContext.enforceCallingOrSelfPermission(
+ Log.v(TAG, "chyj deletePackage packageName="+packageName+" userId="+userId+" flags=0x"+ Integer.toHexString(deleteFlags));
+ if(mDataPreInstallApp != null)
+ if(!mDataPreInstallApp.verifyApp(packageName,false))
+ {
+ try {
+ observer.onPackageDeleted(packageName,
+ PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
+ } catch (RemoteException re) {
+ }
+ return;
+ }
+ else
+ Log.v(TAG, "chyj deletePackage package is not preinstall in Data");
+ else
+ Log.v(TAG, "chyj deletePackage mDataPreInstallApp is not init");
+
+ mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(observer);
arkfjxxdt
说得更好发挥梵蒂冈亿元
第三个try他让你
DataPreInstallApp.java
/*
* Copyright (C) 2013 The TCL Android TV
* TCL Software XI'AN
* yangzp@tcl.com
*/
package com.tcl.os.system.DataPreInstallApp;
import java.io.File;
import android.util.Slog;
import android.os.SystemProperties;
import android.os.FileObserver;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.IPackageManager;
import java.io.PrintWriter;
import java.util.List;
import java.util.ArrayList;
import java.lang.Runnable;
import java.lang.Thread;
public class DataPreInstallApp{
private static final String TAG = "DataPreInstallApp";
public static boolean DEBUG;
private static final String PerIstallPath = "persist.tcl.datapreinstallapp";
private static final String DefaultPath = "/data/user/0/com.tcl.appmarket2/shared_prefs/preinstall_app_data.xml";
ParsePreInstallApp mParseIstallApp;
FileObserver mFileObserver;
File mFile;
IPackageManager mPm;
DataPreInstallApp mDataInstall;
List<String> mPkgs = new ArrayList<String>();
List<PackageInfo> mInstalledPkgs;
private boolean mObservered = false;
private static String mPerIstallPath = "";
private static String mMonitorPath = "";
public DataPreInstallApp(){
if(DEBUG) Slog.d(TAG,"FileObserver startWatching .");
DEBUG = true;//"true".equals(SystemProperties.get("persist.tcl.datapreinstallapp.debug"));
// mPackageSourceInfo = new PackageSourceInfo();
mParseIstallApp = new ParsePreInstallApp();
mPerIstallPath = SystemProperties.get(PerIstallPath);
mPerIstallPath = (mPerIstallPath.equals("") || mPerIstallPath == null) ? DefaultPath : mPerIstallPath;
mDataInstall = this;
}
public void update(){
DEBUG = true;//"true".equals(SystemProperties.get("persist.tcl.datapreinstallapp.debug"));
if(DEBUG) Slog.d(TAG,"update starting ... ");
synchronized (mParseIstallApp) {
mParseIstallApp.updateAPPList(mPerIstallPath);
}
if(mFileObserver == null || !mObservered){
mPerIstallPath = SystemProperties.get(PerIstallPath);
mPerIstallPath = (mPerIstallPath.equals("") || mPerIstallPath == null) ? DefaultPath : mPerIstallPath;
mMonitorPath = mPerIstallPath.substring(0,mPerIstallPath.lastIndexOf('/'));
mFile = new File(mMonitorPath);
if(mFile.exists() && mFile.canRead()){
if(DEBUG) Slog.d(TAG,"FileObserver : " + mMonitorPath);
mFileObserver = new FileObserver(mMonitorPath,FileObserver.ALL_EVENTS){
@Override
public void onEvent(int event,String path){
if((event & (FileObserver.CLOSE_WRITE | FileObserver.ATTRIB)) != 0){
if(DEBUG && path != null) Slog.d(TAG,"FileObserver recieve event : " + ((event == 8)? "write close":"attrib (permission) changed") + "recieve path : " + path);
if(path.equals(mPerIstallPath.substring(mPerIstallPath.lastIndexOf('/') + 1 ,mPerIstallPath.length()))){
File file = new File(mPerIstallPath);
if(file.exists() && file.canRead()){
synchronized(mParseIstallApp){
mParseIstallApp.updateAPPList(mPerIstallPath);
//mDataInstall.updateAppState();
}
}
}
}
}//end of onEvent()
};
if(DEBUG) Slog.d(TAG,"FileObserver startWatching .");
mFileObserver.startWatching();
mObservered = true;
}
}
}
@SuppressWarnings("unchecked")
private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
throws RemoteException {
ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags,userId);
return slice.getList();
}
public boolean verifyApp(String pkgName ,boolean booting){
if(DEBUG) Slog.d(TAG,"verifyApp pkgName="+pkgName+" booting="+booting);
if(!booting && (mParseIstallApp.mDataPreInstallApps == null || mParseIstallApp.mDataPreInstallApps.isEmpty())){
update();
}
synchronized (mParseIstallApp) {
if(mParseIstallApp.mDataPreInstallApps.contains(pkgName)){
if(DEBUG) Slog.d(TAG,"pkgName="+pkgName+" is System PreInstall App can't uninstall");
return false;
}
}
if(DEBUG) Slog.d(TAG,"pkgName="+pkgName+" is not System PreInstall App will uninstall");
return true;
}
public void dump(PrintWriter pw){
pw.println("------DataPreInstallApp dump :");
int i = 0;
for(String name : mParseIstallApp.mDataPreInstallApps){
i++;
pw.println("--" + i + "-- data pre install app : " + name + ";");
}
pw.println("===========================");
if(mPerIstallPath != null)
pw.println("-- preinstall data app file path : " + mPerIstallPath);
pw.println("----------DataPreInstallApp Dump end -------");
}
}
几室几厅
开裆裤论坛
ParsePreInstallApp.java
/*
* Copyright (C) 201706 The TCL Android TV
* TCL Software XI'AN
* yangzp@tcl.com
*/
package com.tcl.os.system.DataPreInstallApp;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Slog;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ParsePreInstallApp{
private final static String TAG = "ParsePreInstallApp";
ArrayList<String> mDataPreInstallApps= new ArrayList<String>();
ArrayList<String> mOldDataPreInstallApps= new ArrayList<String>();
public ParsePreInstallApp(){
if(DataPreInstallApp.DEBUG) Slog.d(TAG," new ParsePreInstallApp ");
}
private DefaultHandler mDefaultHandler = new DefaultHandler() {
private boolean appList = false;
private StringBuilder value;
private String attr;
private String str;
@Override
public void startDocument () throws SAXException {
super.startDocument();
value = new StringBuilder();
str = "";
attr = "";
appList = false;
mOldDataPreInstallApps.clear();
mOldDataPreInstallApps.addAll(mDataPreInstallApps);
mDataPreInstallApps.clear();
}
@Override
public void endDocument () throws SAXException {
super.endDocument();
value = new StringBuilder();
str = "";
attr = "";
appList = false;
}
@Override
public void error(SAXParseException e) throws SAXException {
super.error(e);
Slog.e(TAG,"parse error .");
e.printStackTrace();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if(DataPreInstallApp.DEBUG) Slog.d(TAG,"uri : " + uri + ";\n localName : " + localName +
";\n qName :" + qName + ";\n attributes.getValue(0) :" + attributes.getValue(0));
if(localName.trim().equals("set")){
attr = attributes.getValue(0).trim();
if("DataPreInstallApps".equals(attr)){
appList = true;
}
}
}
@Override
public void characters(char ch[], int start, int length)throws SAXException {
super.characters(ch,start,length);
value.append(new String(ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri,localName,qName);
str = trimStr(value.toString());
if(str != null && !str.equals("")){
if(appList && !mDataPreInstallApps.contains(str)){
if(DataPreInstallApp.DEBUG) Slog.d(TAG,"add to mDataPreInstallApps : " + str);
mDataPreInstallApps.add(str);
}
}
value.delete(0,value.length());
if(localName.trim().equals("set")){
appList = false;
}
}
};
String trimStr(String str){
if(DataPreInstallApp.DEBUG) Slog.d(TAG,"trimStr enter str = " + str);
String res = "";
Pattern pattern = Pattern.compile("\\s*|\t|\r|\n");
if(str != null){
Matcher m = pattern.matcher(str);
res = m.replaceAll("");
}
if(DataPreInstallApp.DEBUG) Slog.d(TAG,"trimStr exit res = " + res);
return res;
}
public void updateAPPList(String path){
if(DataPreInstallApp.DEBUG) Slog.d(TAG,"updateAPPList .");
onParsePreIstallAppListXml(path);
}
public ArrayList<String> getPreInstallApps(){
return mDataPreInstallApps;
}
private void onParsePreIstallAppListXml(String xmlFileName) {
if(DataPreInstallApp.DEBUG) Slog.d(TAG, "Parse pre install data App list from xml's file!");
File file = new File(xmlFileName);
String res = "";
if (file.exists()) {
if(DataPreInstallApp.DEBUG) Slog.d(TAG,"onParsePreIstallAppListXml file : " + xmlFileName);
if(!file.canRead()){
Slog.d(TAG,"can not read file : " + xmlFileName);
}
try {
InputStream in = new FileInputStream(file);
int length = in.available();
if(length <= 0){
in.close();
Slog.d(TAG,"onParsePreIstallAppListXml file :" + xmlFileName + " size <=0 or Other Exception");
return;
}
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(in,mDefaultHandler);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
反对虎头虎脑
preinstall_app_data.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<set name="DataPreInstallApps">
<string>com.tcl.qiyiguo</string>
<string>com.starcor.mango</string>
</set>
</map>