Skip to content

Commit

Permalink
Merge pull request iqiyi#40 from iqiyi/dev
Browse files Browse the repository at this point in the history
merge dev
  • Loading branch information
ziyang0116 authored Jan 16, 2021
2 parents 7fd2b19 + 08ceda5 commit 1ec461b
Show file tree
Hide file tree
Showing 10 changed files with 340 additions and 3 deletions.
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
gen
bin
target
.idea
.settings
*.iml
.classpath
.project
out
classes
gen-external-apklibs
.DS_Store
.gradle
local.properties
build/
buildSrc/build
*.apk
*.hprof
infer-out/
captures/
*.swp

strings/src/main/generated/
.externalNativeBuild
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,16 @@ public static String findSplitPrimaryAbi(@NonNull String basePrimaryAbi, @NonNul
}
return null;
}

public static boolean isArm64(Context context) {
String baseApi = null;
try {
baseApi = getBasePrimaryAbi(context);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return !TextUtils.isEmpty(baseApi) && baseApi.equals(armv8);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* MIT License
*
* Copyright (c) 2019-present, iQIYI, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.iqiyi.android.qigsaw.core.splitload;

class SkipSplitLoadTaskImpl implements Runnable {

@Override
public final void run() {
// empty
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

import com.iqiyi.android.qigsaw.core.common.SplitConstants;
import com.iqiyi.android.qigsaw.core.common.SplitLog;
import com.iqiyi.android.qigsaw.core.splitload.compat.NativePathMapper;
import com.iqiyi.android.qigsaw.core.splitload.compat.NativePathMapperImpl;
import com.iqiyi.android.qigsaw.core.splitreport.SplitBriefInfo;
import com.iqiyi.android.qigsaw.core.splitreport.SplitLoadError;
import com.iqiyi.android.qigsaw.core.splitrequest.splitinfo.SplitInfo;
Expand Down Expand Up @@ -65,6 +67,8 @@ final class SplitLoadHandler {

private final SplitActivator activator;

private final NativePathMapper mapper;

SplitLoadHandler(@NonNull SplitLoaderWrapper splitLoader,
@NonNull SplitLoadManager loadManager,
@NonNull List<Intent> splitFileIntents) {
Expand All @@ -74,6 +78,7 @@ final class SplitLoadHandler {
this.mainHandler = new Handler(Looper.getMainLooper());
this.infoManager = SplitInfoManagerService.getInstance();
this.activator = new SplitActivator(loadManager.getContext());
this.mapper = new NativePathMapperImpl(loadManager.getContext());
}

Handler getMainHandler() {
Expand Down Expand Up @@ -133,6 +138,12 @@ private void loadSplits(final OnSplitLoadFinishListener loadFinishListener) {
//load split's dex files
List<String> addedDexPaths = splitFileIntent.getStringArrayListExtra(SplitConstants.KEY_ADDED_DEX);
ClassLoader classLoader;

// check if need compat native lib path on android 5.x
SplitLog.d(TAG, "split name: %s, origin native path: %s", splitName, nativeLibPath);
nativeLibPath = mapper.map(splitName, nativeLibPath);
SplitLog.d(TAG, "split name: %s, mapped native path: %s", splitName, nativeLibPath);

try {
classLoader = splitLoader.loadCode(splitName,
addedDexPaths, dexOptPath == null ? null : new File(dexOptPath),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,14 @@ public void getResources(Resources resources) {

@Override
public Runnable createSplitLoadTask(List<Intent> splitFileIntents, @Nullable OnSplitLoadListener loadListener) {
List<Intent> filterSplitFileIntentList = filterIntentsCanWorkInThisProcess(splitFileIntents);
if (filterSplitFileIntentList.isEmpty()) {
return new SkipSplitLoadTaskImpl();
}
if (splitLoadMode() == SplitLoad.MULTIPLE_CLASSLOADER) {
return new SplitLoadTaskImpl(this, splitFileIntents, loadListener);
return new SplitLoadTaskImpl(this, filterSplitFileIntentList, loadListener);
} else {
return new SplitLoadTaskImpl2(this, splitFileIntents, loadListener);
return new SplitLoadTaskImpl2(this, filterSplitFileIntentList, loadListener);
}
}

Expand Down Expand Up @@ -147,6 +151,25 @@ private void loadInstalledSplitsInternal(Collection<String> splitNames) {
createSplitLoadTask(splitFileIntents, null).run();
}

private List<Intent> filterIntentsCanWorkInThisProcess(@NonNull List<Intent> intentList) {
List<Intent> filterIntentList = new ArrayList<>(intentList.size());
SplitInfoManager infoManager = SplitInfoManagerService.getInstance();
if (infoManager == null) {
return intentList;
}
for (Intent splitFileIntent : intentList) {
final String splitName = splitFileIntent.getStringExtra(SplitConstants.KET_NAME);
SplitInfo info = infoManager.getSplitInfo(getContext(), splitName);
if (canBeWorkedInThisProcessForSplit(info)) {
filterIntentList.add(splitFileIntent);
SplitLog.i(TAG, "Split %s need load in process %s", info.getSplitName(), currentProcessName);
} else {
SplitLog.i(TAG, "Split %s do not need load in process %s", info.getSplitName(), currentProcessName);
}
}
return filterIntentList;
}

private boolean isInjectPathClassloaderNeeded() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
return qigsawMode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.iqiyi.android.qigsaw.core.splitload.compat;

public interface NativePathMapper {
String map(String splitName, String originPath);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.iqiyi.android.qigsaw.core.splitload.compat;

import android.content.Context;
import android.os.Build;
import android.text.TextUtils;

import com.iqiyi.android.qigsaw.core.common.AbiUtil;


public class NativePathMapperImpl implements NativePathMapper {

private final NativePathMapper mapper;

public NativePathMapperImpl(Context context) {
if (needUseCommonSoDir(context)) {
mapper = new PathMapperV21(context);
} else {
mapper = new PathMapperAbove21(context);
}
}

@Override
public String map(String splitName, String originPath) {
if (TextUtils.isEmpty(splitName) || TextUtils.isEmpty(originPath)) {
return originPath;
}
synchronized(Runtime.getRuntime()) {
return mapper.map(splitName, originPath);
}
}

private boolean needUseCommonSoDir(Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.M
&& AbiUtil.isArm64(context);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.iqiyi.android.qigsaw.core.splitload.compat;

import android.content.Context;

class PathMapperAbove21 implements NativePathMapper {

private final Context context;

PathMapperAbove21(Context context) {
this.context = context;
}

@Override
public String map(String splitName, String originPath) {
return originPath;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package com.iqiyi.android.qigsaw.core.splitload.compat;

import java.io.File;
import java.io.FilenameFilter;

import android.content.Context;
import android.os.Build;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import androidx.annotation.RequiresApi;

import com.iqiyi.android.qigsaw.core.common.SplitConstants;
import com.iqiyi.android.qigsaw.core.common.SplitLog;
import com.iqiyi.android.qigsaw.core.splitrequest.splitinfo.SplitPathManager;

/**
* compat library name too long on android 5.x
* ref: https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:bionic/linker/linker.cpp
* method: soinfo_alloc
*
* #define SOINFO_NAME_LEN 128
*
* if (strlen(name) >= SOINFO_NAME_LEN) {
* DL_ERR("library name \"%s\" too long", name);
* return nullptr;
* }
*
*/

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
class PathMapperV21 implements NativePathMapper {

private static final String TAG = "Split:PathMapper";
private static final int MAX_LIB_PATH = 128;

private final Context context;
private final File commonDir;


PathMapperV21(Context context) {
this.context = context;
commonDir = SplitPathManager.require().getCommonSoDir();
}

@Override
public String map(String splitName, String originPath) {
boolean isNeedMap = checkIfNeedMapPath(originPath);
if (!isNeedMap) {
SplitLog.d(TAG, "do not need map native lib path: %s", originPath);
return originPath;
}
if (!commonDir.exists()) {
boolean mkdirResult = commonDir.mkdirs();
if (!mkdirResult) {
SplitLog.d(TAG, "mkdir: %s failed", commonDir.getAbsolutePath());
return originPath;
}
}
File targetFile = new File(commonDir, splitName);
boolean linkResult = symLink(new File(originPath), targetFile, false);
if (linkResult) {
return targetFile.getAbsolutePath();
} else {
return originPath;
}
}

private boolean checkIfNeedMapPath(String libPath) {
if (TextUtils.isEmpty(libPath)) {
return false;
}
File libDir = new File(libPath);
if (!libDir.exists()) {
return false;
}
File[] soFileArray = libDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return !TextUtils.isEmpty(name) && name.endsWith(SplitConstants.DOT_SO);
}
});
if (soFileArray == null || soFileArray.length == 0) {
return false;
}
for (File soFile : soFileArray) {
if (soFile != null && !TextUtils.isEmpty(soFile.getAbsolutePath()) && soFile.getAbsolutePath().length() >= MAX_LIB_PATH) {
SplitLog.d(TAG, "need map native lib path: %s length >= %d", commonDir.getAbsolutePath(), MAX_LIB_PATH);
return true;
}
}
return false;
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private boolean symLink(File source, File target, boolean isRetry) {
String sourcePath = source.getAbsolutePath();
if (!source.exists()) {
SplitLog.e(TAG, "symLink source: " + sourcePath + " not exist");
return false;
}
String targetPath = target.getAbsolutePath();
if (target.exists()) {
boolean isPathEqual = isSymlinkFileEqual(sourcePath, targetPath);
if (isPathEqual) {
return true;
} else {
if (!target.delete()) {
SplitLog.e(TAG, "delete symLink target: " + targetPath+ " fail");
return false;
}
}
}

try {
Os.symlink(sourcePath, targetPath);
} catch (Throwable e) {
e.printStackTrace();
if (e instanceof ErrnoException && ((ErrnoException) e).errno == OsConstants.EEXIST) {
SplitLog.d(TAG, "create symLink exist, from: " + sourcePath + " to: " + targetPath);
boolean isPathEqual = isSymlinkFileEqual(sourcePath, targetPath);
if (isPathEqual) {
return true;
} else {
SplitLog.d(TAG, "delete exist symLink, " + " targetPath: " + targetPath);
target.delete();
if (!isRetry) {
return symLink(source, target, true);
}
}
}
return false;
}
SplitLog.d(TAG, "create symLink success from: " + sourcePath + " to: " + targetPath);
return true;
}

private boolean isSymlinkFileEqual(String sourcePath, String targetPath) {
SplitLog
.d(TAG, "isSymlinkFileEqual, " + " sourcePath: " + sourcePath + " targetPath: " + targetPath);
try {
String oldSourcePath = Os.readlink(targetPath);
SplitLog.d(TAG, "isSymlinkFileEqual, " + " sourcePath: " + sourcePath + " oldSourcePath: " + oldSourcePath);
if (!TextUtils.isEmpty(oldSourcePath)) {
return oldSourcePath.equals(sourcePath);
}
} catch (ErrnoException e) {
e.printStackTrace();
}
return false;
}

}
Loading

0 comments on commit 1ec461b

Please sign in to comment.