Android系统预置应用宝
如果直接按照常规方案预置应用宝到system/app下的话,会报好多Selinux错误,导致应用闪退
而应用宝又申请了好多并不需要的权限例如su
本来的方案是第一次开机时用packageinstaller静默安装应用宝
但是效果不太好,会出现桌面图标加载完以后才安装显示应用宝
所以需要添加个系统服务,在systemserver里面启动安装
系统编译需要先把应用宝预置到/product/etc/app/yingyongbao.apk
frameworks / base/services/java/com/android/server/SystemServer.java
t.traceBegin("StartBootPhaseDeviceSpecificServicesReady");
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
t.traceEnd();
ConcurrentUtils.waitForFutureNoInterrupt(mBlobStoreServiceStart,
START_BLOB_STORE_SERVICE);
// add by songhui for silent install apk ---------------------加载时机不要太靠前,需要等pms systemReady后加载
if(android.os.SystemProperties.get("ro.xxxxx_install").equals("1")){
t.traceBegin("SilentInstallService");
mSystemServiceManager.startService(SilentInstallService.class);
t.traceEnd();
}
// add by songhui for silent install apk
frameworks / base/services/install/java/com/android/server/install/SilentInstallService.java
package com.android.server.install;
import android.content.Context;
import com.android.server.SystemService;
import android.content.pm.PackageInfo;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.BufferedReader;
import java.util.List;
import android.content.pm.IPackageManager;
import android.app.AppGlobals;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.content.pm.PackageInstaller;
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;
public class SilentInstallService extends SystemService {
private Context mContext;
private String apkPath;
private IPackageManager pm;
private File[] apklist;
private String LOG_TAG = "SilentInstallService";
public SilentInstallService(Context context) {
super(context);
mContext = context ;
pm = AppGlobals.getPackageManager();
apklist = new File("/product/etc/app/").listFiles();
}
@Override
public void onStart() {
try {
if(pm.isFirstBoot()) {
ThreadPoolManager.getInstance().execute(new Runnable() {
@Override
public void run() {
for(File file : apklist) {
if(file.isFile() && file.getName().endsWith(".apk")) {
install28(mContext, file.getAbsolutePath());
}
}
}
});
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public void install28(Context context, String apkFilePath) {
Log.i(LOG_TAG, "install28 apkFilePath=" + apkFilePath);
File apkFile = new File(apkFilePath);
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams sessionParams
= new PackageInstaller.SessionParams(PackageInstaller
.SessionParams.MODE_FULL_INSTALL);
sessionParams.setSize(apkFile.length());
int sessionId = createSession(packageInstaller, sessionParams);
Log.i(LOG_TAG, "install28 sessionId=" + sessionId);
if (sessionId != -1) {
boolean copySuccess = copyInstallFile(packageInstaller, sessionId, apkFilePath);
Log.d(LOG_TAG, "install28 copySuccess=" + copySuccess);
if (copySuccess) {
execInstallCommand(context, packageInstaller, sessionId);
}
}
}
public int createSession(PackageInstaller packageInstaller,
PackageInstaller.SessionParams sessionParams) {
int sessionId = -1;
try {
sessionId = packageInstaller.createSession(sessionParams);
} catch (IOException e) {
e.printStackTrace();
}
return sessionId;
}
public boolean copyInstallFile(PackageInstaller packageInstaller,
int sessionId, String apkFilePath) {
InputStream in = null;
OutputStream out = null;
PackageInstaller.Session session = null;
boolean success = false;
try {
File apkFile = new File(apkFilePath);
session = packageInstaller.openSession(sessionId);
out = session.openWrite("base.apk", 0, apkFile.length());
in = new FileInputStream(apkFile);
int total = 0, c;
byte[] buffer = new byte[65536];
while ((c = in.read(buffer)) != -1) {
total += c;
out.write(buffer, 0, c);
}
session.fsync(out);
Log.i(LOG_TAG, "streamed " + total + " bytes");
success = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return success;
}
public void execInstallCommand(Context context, PackageInstaller packageInstaller, int sessionId) {
PackageInstaller.Session session = null;
try {
session = packageInstaller.openSession(sessionId);
Intent intent = new Intent(context, InstallResultReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());
Log.i(LOG_TAG, "begin session");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
}
frameworks / base/services/install/java/com/android/server/install/InstallResultReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
public class InstallResultReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
// success
} else {
//Log.e(TAG, intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
}
}
}
}
frameworks / base/services/install/java/com/android/server/install/ThreadPoolManager.java
import java.util.concurrent.TimeUnit;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.Executors;
public class ThreadPoolManager {
private static final String TAG = "ThreadPoolManager";
private static ThreadPoolManager mInstance = new ThreadPoolManager();
public static ThreadPoolManager getInstance() {
return mInstance;
}
private int corePoolSize;
private int maximumPoolSize;
private long keepAliveTime = 1;
private TimeUnit unit = TimeUnit.SECONDS;
private ThreadPoolExecutor executor;
private ThreadPoolManager() {
corePoolSize = Runtime.getRuntime().availableProcessors()*2+1;
maximumPoolSize = corePoolSize;
executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
}
public void execute(Runnable runnable){
if(runnable==null)return;
executor.execute(runnable);
}
public void remove(Runnable runnable){
if(runnable==null)return;
executor.remove(runnable);
}
}