Resolved the issue of "Overwriting the plug-in, it may not be notified to other processes"

Also modified:
* Added the "getParentInfo" method in the PluginInfo class
* IsNewOrUpdatedPlugin removed from PmBase because it is no longer needed
This commit is contained in:
zhangjiongxuan 2017-08-08 18:42:24 +08:00
parent 1b346fbc1f
commit 4fb15f8c41
4 changed files with 62 additions and 62 deletions

View File

@ -32,7 +32,6 @@ import android.text.TextUtils;
import com.qihoo360.i.Factory;
import com.qihoo360.i.IModule;
import com.qihoo360.i.IPluginManager;
import com.qihoo360.replugin.utils.ReflectUtils;
import com.qihoo360.mobilesafe.api.Tasks;
import com.qihoo360.replugin.IHostBinderFetcher;
import com.qihoo360.replugin.RePlugin;
@ -49,6 +48,7 @@ import com.qihoo360.replugin.helper.LogDebug;
import com.qihoo360.replugin.helper.LogRelease;
import com.qihoo360.replugin.model.PluginInfo;
import com.qihoo360.replugin.packages.PluginManagerProxy;
import com.qihoo360.replugin.utils.ReflectUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@ -997,20 +997,6 @@ class PmBase {
return mPlugins.get(plugin);
}
// 是否为新的或已经更新过的插件
// 注意插件正在运行时触发更新则这里应返回false这样外界将不会发送新插件广播
final boolean isNewOrUpdatedPlugin(PluginInfo info) {
Plugin p = mPlugins.get(info.getName());
// 满足三个条件的其一就表示为"新插件"可以做下一步处理
// 1. p为空表示为全新插件
// 2. 要安装的版本比当前的要高且未运行
// 3. "待定更新"插件插件未运行
return p == null ||
(p.mInfo.getVersionValue() < info.getVersionValue() && !RePlugin.isPluginRunning(info.getName())) ||
(info.getPendingUpdate() != null && !RePlugin.isPluginRunning(info.getName()));
}
final Plugin loadPackageInfoPlugin(String plugin, PluginCommImpl pm) {
Plugin p = Plugin.cloneAndReattach(mContext, mPlugins.get(plugin), mClassLoader, pm);
return loadPlugin(p, Plugin.LOAD_INFO, true);

View File

@ -328,28 +328,45 @@ class PmHostSvc extends IPluginHost.Stub {
}
if (pi != null) {
// 插件是否需要更新
if (!mPluginMgr.isNewOrUpdatedPlugin(pi)) {
return pi;
}
// 常驻进程上下文
mPluginMgr.newPluginFound(pi, false);
// 通知其它进程
Intent intent = new Intent(PmBase.ACTION_NEW_PLUGIN);
intent.putExtra(RePluginConstants.KEY_PERSIST_NEED_RESTART, mNeedRestart);
intent.putExtra("obj", pi);
IPC.sendLocalBroadcast2AllSync(mContext, intent);
if (LOG) {
LogDebug.d(PLUGIN_TAG, "pluginDownloaded complete, info=" + pi);
}
// 通常到这里表示安装已成功这时不管处于什么状态都应该通知外界更新插件内存表
syncPluginInfo2All(pi);
}
return pi;
}
private void syncPluginInfo2All(PluginInfo pi) {
// PS若更新了正在运行的插件属于下次重启进程后更新则由于install返回的是新的PluginInfo为防止出现错误更新需要使用原来的
//
// 举例有一个正在运行的插件A其Info为PluginInfoOld升级到新版其Info为PluginInfoNew
// 1. mManager.getService().install(path) 的返回值为PluginInfoNew
// 2. PluginInfoOld在常驻进程中的内容修改为PluginInfoOld.mPendingUpdate = PendingInfoNew
// 3. 同步到各进程这里存在两种可能
// a) 有问题同步的是PluginInfoNew则所有进程的内存表都强制更新到新的Info上因此正在运行的插件信息将丢失会出现严重问题
// b) 没问题同步的是PluginInfoOld只不过这个Old里面有个mPendingUpdate指向PendingInfoNew则不会有问题旧的仍被使用符合预期
// 4. 最终install方法的返回值是PluginInfoNew这样最外面拿到的就是安装成功的新插件信息符合开发者的预期
PluginInfo needToSyncPi;
PluginInfo parent = pi.getParentInfo();
if (parent != null) {
needToSyncPi = parent;
} else {
needToSyncPi = pi;
}
// 在常驻进程内更新插件内存表
mPluginMgr.newPluginFound(needToSyncPi, false);
// 通知其它进程去更新
Intent intent = new Intent(PmBase.ACTION_NEW_PLUGIN);
intent.putExtra(RePluginConstants.KEY_PERSIST_NEED_RESTART, mNeedRestart);
intent.putExtra("obj", needToSyncPi);
IPC.sendLocalBroadcast2AllSync(mContext, intent);
if (LOG) {
LogDebug.d(TAG, "syncPluginInfo2All: Sync complete! syncPi=" + needToSyncPi);
}
}
private PluginInfo pluginDownloadedForPn(String path) {
File f = new File(path);
V5FileInfo v5f = V5FileInfo.build(f, V5FileInfo.NORMAL_PLUGIN);

View File

@ -34,8 +34,8 @@ import com.qihoo360.replugin.RePlugin;
import com.qihoo360.replugin.RePluginInternal;
import com.qihoo360.replugin.helper.JSONHelper;
import com.qihoo360.replugin.helper.LogDebug;
import com.qihoo360.replugin.utils.FileUtils;
import org.json.JSONException;
import org.json.JSONObject;
@ -101,14 +101,18 @@ public class PluginInfo implements Parcelable, Cloneable {
// 若插件需要更新则会有此值
private PluginInfo mPendingUpdate;
private boolean mIsThisPendingUpdateInfo;
// 若插件需要卸载则会有此值
private PluginInfo mPendingDelete;
// 若插件需要同版本覆盖安装更新则会有此值
private PluginInfo mPendingCover;
private boolean mIsPendingCover;
private boolean mIsPendingCover; // 若当前为新的PluginInfo且为同版本覆盖则为了能区分路径则需要将此字段同步到Json文件中
// 若当前为新的PluginInfo则其父Info是什么
// 通常当前这个Info会包裹在mPendingUpdate/mPendingDelete/mPendingCover
// 此信息不会做持久化工作下次重启进程后会消失
private PluginInfo mParentInfo;
private PluginInfo(JSONObject jo) {
initPluginInfo(jo);
@ -150,7 +154,6 @@ public class PluginInfo implements Parcelable, Cloneable {
*/
public PluginInfo(PluginInfo pi) {
this.mJson = JSONHelper.cloneNoThrows(pi.mJson);
this.mIsThisPendingUpdateInfo = pi.mIsThisPendingUpdateInfo;
if (pi.mPendingUpdate != null) {
this.mPendingUpdate = new PluginInfo(pi.mPendingUpdate);
}
@ -161,6 +164,9 @@ public class PluginInfo implements Parcelable, Cloneable {
if (pi.mPendingCover != null) {
this.mPendingCover = new PluginInfo(pi.mPendingCover);
}
if (pi.mParentInfo != null) {
this.mParentInfo = new PluginInfo(pi.mParentInfo);
}
}
private void initPluginInfo(JSONObject jo) {
@ -206,11 +212,6 @@ public class PluginInfo implements Parcelable, Cloneable {
*/
public static PluginInfo parseFromPackageInfo(PackageInfo pi, String path) {
ApplicationInfo ai = pi.applicationInfo;
if (ai == null) {
// 几乎不可能但为保险起见返回Null
return null;
}
String pn = pi.packageName;
String alias = null;
int low = 0;
@ -322,9 +323,9 @@ public class PluginInfo implements Parcelable, Cloneable {
if (isPnPlugin()) {
// 为兼容以前逻辑p-n仍是判断dex是否存在
return isDexExtracted();
} else if (isThisPendingUpdateInfo()) {
} else if (getParentInfo() != null) {
// 若PluginInfo是其它PluginInfo中的PendingUpdate则返回那个PluginInfo的Used即可
return RePlugin.isPluginUsed(getName());
return getParentInfo().isUsed();
} else {
// 若是纯APK且不是PendingUpdate则直接从Json中获取
return mJson.optBoolean("used");
@ -625,9 +626,7 @@ public class PluginInfo implements Parcelable, Cloneable {
setFrameworkVersion(frameVer);
}
/**
* 获取JSON对象仅内部使用
*/
// @hide
public JSONObject getJSON() {
return mJson;
}
@ -669,21 +668,17 @@ public class PluginInfo implements Parcelable, Cloneable {
}
/**
* 此PluginInfo是否是一个位于其它PluginInfo中的PendingUpdate只在调用RePlugin.install方法才能看到 <p>
* 注意仅框架内部使用
* 若此Info为新PluginInfo则这里返回的是其父Info的内容通常和PendingUpdate有关
*
* @return 是否是PendingUpdate的PluginInfo
* @return PluginInfo
*/
public boolean isThisPendingUpdateInfo() {
return mIsThisPendingUpdateInfo;
public PluginInfo getParentInfo() {
return mParentInfo;
}
/**
* 此PluginInfo是否是一个位于其它PluginInfo中的PendingUpdate <p>
* 注意仅框架内部使用
*/
public void setIsThisPendingUpdateInfo(boolean updateInfo) {
mIsThisPendingUpdateInfo = updateInfo;
// @hide
public void setParentInfo(PluginInfo parent) {
mParentInfo = parent;
}
static PluginInfo createByJO(JSONObject jo) {
@ -769,8 +764,8 @@ public class PluginInfo implements Parcelable, Cloneable {
}
// 当前是否为PendingUpdate的信息
if (mIsThisPendingUpdateInfo) {
b.append("[isTPUI] ");
if (mParentInfo != null) {
b.append("[HAS_PARENT] ");
}
// 插件类型

View File

@ -28,16 +28,16 @@ import com.qihoo360.loader2.CertUtils;
import com.qihoo360.loader2.MP;
import com.qihoo360.loader2.PluginNativeLibsHelper;
import com.qihoo360.mobilesafe.api.Tasks;
import com.qihoo360.replugin.utils.pkg.PackageFilesUtil;
import com.qihoo360.replugin.RePlugin;
import com.qihoo360.replugin.RePluginEventCallbacks;
import com.qihoo360.replugin.RePluginInternal;
import com.qihoo360.replugin.base.IPC;
import com.qihoo360.replugin.utils.FileUtils;
import com.qihoo360.replugin.helper.LogDebug;
import com.qihoo360.replugin.helper.LogRelease;
import com.qihoo360.replugin.model.PluginInfo;
import com.qihoo360.replugin.model.PluginInfoList;
import com.qihoo360.replugin.utils.FileUtils;
import com.qihoo360.replugin.utils.pkg.PackageFilesUtil;
import java.io.File;
import java.io.IOException;
@ -297,7 +297,6 @@ public class PluginManagerServer {
}
if (instPli.getVersion() > curPli.getVersion()) {
// 高版本升级
instPli.setIsThisPendingUpdateInfo(true);
curPli.setPendingUpdate(instPli);
curPli.setPendingDelete(null);
curPli.setPendingCover(null);
@ -313,6 +312,9 @@ public class PluginManagerServer {
LogDebug.w(TAG, "updateOrLater: Plugin need update same version. clear PendingDelete.");
}
}
// 设置其Parent为curPli在PmBase.newPluginFound时会用到
instPli.setParentInfo(curPli);
} else {
if (LogDebug.LOG) {
LogDebug.i(TAG, "updateOrLater: Not running. Update now! pn=" + curPli.getName());