1.準備
二つの情報の二重開放システムは、アプリケーションを比較します
比較1.1ディレクトリ
1.1.1データディレクトリの比較
オリジナルアプリケーション:
/data/user/0/com.luoyesiqiu.crackme/files
コピーしたアプリケーション:
/data/user/999/com.luoyesiqiu.crackme/files
1.1.2 APKディレクトリ比較
オリジナルアプリケーション:
/data/app/com.luoyesiqiu.crackme-H1Dvbka0t42rzlCAqSpgHQ==/base.apk
コピーしたアプリケーション:
/data/app/com.luoyesiqiu.crackme-H1Dvbka0t42rzlCAqSpgHQ==/base.apk
APK比較することによって、インストールディレクトリとデータディレクトリ、我々はシステムがオープンデュアルであることを知ることができるシェアは同じAPK、それが持っている別のデータディレクトリを。
1.2比較プロセス情報
USER PID PPID VSZ RSS WCHAN ADDR S NAME
u0_a161 30284 918 2276572 48420 SyS_epoll_wait 0 S com.luoyesiqiu.crackme
u999_a161 30311 918 2276572 48004 SyS_epoll_wait 0 S com.luoyesiqiu.crackme
情報の過程を見ることによって、あなたは、これら2つのアプリケーションが上で実行されていることを知ることができるさまざま内のユーザー。
これと同様の機能を実現するために、我々は、以下の設定を行います。
2.制限を変更するためのユーザーを作成します。
Android5.0当初から、Androidはプロファイルの作成をサポートしています。デフォルトでは、システムがあるだけで、オープンの新しいマルチユーザの作成を可能にするダブルオープンだけでなく、あなたが複数のユーザーリーチを作成するためのソースコードを変更することができます。
変更frameworks/base/services/core/java/com/android/server/pm/UserManagerService.java
MAX_MANAGED_PROFILESフィールドのは、あなたが作成したいユーザーの最大数を変更し、そのデフォルト値は1です。
3.ユーザーを作成します。
ユーザーを作成すると、ユーザーを作成し、それを開くために、createProfile方法、フラグ、着信0x00000020を呼び出して、より開かれた容器を作成することです
private static int getUserIdFromUserInfo(Object userInfo) {
int userId = -1;
try {
Field field_id = userInfo.getClass().getDeclaredField("id");
field_id.setAccessible(true);
userId = (Integer)field_id.get(userInfo);
} catch (Exception e) {
e.printStackTrace();
}
return userId;
}
public boolean startUser(int userId){
Object iActivityManager = null;
try {
iActivityManager = Class.forName("android.app.ActivityManagerNative").getMethod("getDefault").invoke(null);
boolean isOk=(boolean)iActivityManager.getClass().getMethod("startUserInBackground",int.class)
.invoke(iActivityManager,userId);
return isOk;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public String createProfile(Context context, String userName, int flag) {
UserManager mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
UserHandle userHandle = UserHandle.getUserHandleForUid(0);
Log.d(TAG,"userHandle = "+userHandle.toString());
try {
int getIdentifier=(int)userHandle.getClass().getMethod("getIdentifier").invoke(userHandle);
Log.d(TAG,"Identifier = "+getIdentifier);
mUserInfo=mUserManager.getClass().getMethod("createProfileForUser",String.class, int.class, int.class)
.invoke(mUserManager
,userName
, flag
,getIdentifier);
if(mUserInfo==null){
Log.d(TAG, "mUserInfo is null!");
return null;
}
int userId = getUserIdFromUserInfo(mUserInfo);
boolean isOk=startUser(userId);
Log.d(TAG, "startUserInBackground() userId = " + userId + " | isOk = " + isOk);
return isOk ? ""+userId : null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
注:マニフェストのノードAndroidManifest.xmlを追加するには、Appユーザーを作成し
android:sharedUserId="android.uid.system"
、フィールドを追加する<uses-permission android:name="android.permission.MANAGE_USERS"/>
権限をするだけでなく、署名するシステムのプラットフォームAPKの署名を使用して。
4.システム構成は、サブユーザのインストールに適用されていません
新しいユーザーを作成するとき、デフォルトでは、システムはユーザーに新しいアプリケーションシステムのコピーを与えるだろうが、我々は、サブユーザシステムのアプリケーションを必要としないので、我々はサブアプリケーションのユーザーがこれらのシステムのインストールをキャンセルしなければなりません。
注意:システムがサブユーザにアプリケーションをインストールすることはできませんが、システムはサブユーザにサービスを提供するためにインストールする必要があり、そうでない場合は、サブユーザにアプリケーションを実行すると、正常に機能しない場合があります。
修改フレームワーク/ベース/サービス/コア/ javaの/ COM /アンドロイド/サーバー/午後/ Settings.java
createNewUserLI方法、システムアプリケーションおよびシステムサービスを構成するサブユーザーにインストールされています。
private final String[] excludeLiStrings={
"android",
"android.ext.services",
"android.ext.shared",
"com.android.bluetooth",
"com.android.htmlviewer",
"com.android.inputdevices",
"com.android.shell",
"com.android.certinstaller",
"com.android.externalstorage",
"com.android.providers.contacts",
"com.android.providers.downloads",
"com.android.providers.media",
"com.android.providers.settings",
"com.android.providers.userdictionary",
"com.android.server.telecom",
"com.android.packageinstaller",
"com.android.settings",
"com.android.providers.telephony",
"com.android.mms.service",
"com.android.webview",
"com.android.location.fused",
"com.android.cts.priv.ctsshim",
"com.android.statementservice",
"com.android.defcontainer",
"com.android.keychain",
"com.android.proxyhandler",
"com.android.dreams.basic",
"com.android.printspooler",
"com.android.pacprocessor",
"com.android.providers.downloads.ui"
};
private boolean isInExcludeList(String pkg){
for(String excludePkg:excludeLiStrings){
if(excludePkg.equals(pkg)){
return true;
}
}
return false;
}
void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer,
int userHandle) {
String[] volumeUuids;
String[] names;
int[] appIds;
String[] seinfos;
int[] targetSdkVersions;
int packagesCount;
synchronized (mPackages) {
Collection<PackageSetting> packages = mPackages.values();
packagesCount = packages.size();
volumeUuids = new String[packagesCount];
names = new String[packagesCount];
appIds = new int[packagesCount];
seinfos = new String[packagesCount];
targetSdkVersions = new int[packagesCount];
Iterator<PackageSetting> packagesIterator = packages.iterator();
for (int i = 0; i < packagesCount; i++) {
PackageSetting ps = packagesIterator.next();
if (ps.pkg == null || ps.pkg.applicationInfo == null) {
continue;
}
// Only system apps are initially installed.
//Slog.w(TAG, "User handle:"+userHandle+",pkg name:"+ps.name);
//修改的地方,在列表外的应用不安装到子用户
if(userHandle > 0 && !isInExcludeList(ps.name)){
ps.setInstalled(false, userHandle);
}
else{
ps.setInstalled(ps.isSystem(), userHandle);
}
// Need to create a data directory for all apps under this user. Accumulate all
// required args and call the installer after mPackages lock has been released
volumeUuids[i] = ps.volumeUuid;
names[i] = ps.name;
appIds[i] = ps.appId;
seinfos[i] = ps.pkg.applicationInfo.seinfo;
targetSdkVersions[i] = ps.pkg.applicationInfo.targetSdkVersion;
}
}
for (int i = 0; i < packagesCount; i++) {
if (names[i] == null) {
continue;
}
// TODO: triage flags!
final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
try {
installer.createAppData(volumeUuids[i], names[i], userHandle, flags, appIds[i],
seinfos[i], targetSdkVersions[i]);
} catch (InstallerException e) {
Slog.w(TAG, "Failed to prepare app data", e);
}
}
synchronized (mPackages) {
applyDefaultPreferredAppsLPw(service, userHandle);
}
}
ソフトウェアをインストールおよびアンインストールするためのシステム以外のユーザー
- 特定のユーザーのアプリに取り付けられました
pm install -t -r --user <userId> <apkPath>
-tは、インストールとテストアプリケーションを可能に
-r既存の置き換え
インストールするには、指定したユーザー--user
注意:デフォルトのランチャー(ランチャー)を再起動するアプリをインストールした後、それ以外の場合は奇妙な質問を表示される場合があります
- 指定されたユーザーからのアプリをアンインストールします
pm uninstall --user <userId> <pkgName>
6.設定アプリケーションは、デフォルトではメインのユーザに取り付けられたのみ
あなたが呼び出す場合オープナーユーザーの後、adb install
またはpm install
APKをインストールするには、APKは、すべてのユーザーに対してインストールされます。これは、私たちが望むものではありませんので、我々はアプリをインストールするために、これらのコマンドを実行するだけのプライマリユーザーを変更しました。
最初のステップは:使用の午後installコマンドのためのAPK道をインストール
フレームワーク/ベース/ CMDS / PM / SRC / COM /アンドロイド/コマンド/午後/ Pm.java
private static class InstallParams {
SessionParams sessionParams;
String installerPackageName;
//int userId = UserHandle.USER_ALL;
int userId = UserHandle.USER_SYSTEM;
}
ステップ2:ADB installコマンドを使用する方法のためのAPKをインストール
システムの古いバージョンでは、adb install
それが呼び出したpm install
APKをインストールするのではなく、システムの新バージョンで呼び出しますcmd package
APKをインストールするコマンドを。
package
で実行する特定のコマンド:
フレームワーク/ベース/サービス/コア/ javaの/ COM /アンドロイド/サーバー/午後/ PackageManagerShellCommand.java
だから、次のコードを変更します。
private static class InstallParams {
SessionParams sessionParams;
String installerPackageName;
//int userId = UserHandle.USER_ALL;
int userId = UserHandle.USER_SYSTEM;
}
7.ユーザーの削除
adb shell pm remove-user <userId>
または、次のコードの削除を呼び出します
public void deleteUser(Context context,int userId){
UserManager userManager=(UserManager) context.getSystemService(Context.USER_SERVICE);
try {
userManager.getClass().getMethod("removeUser",int.class).invoke(userManager,userId);
} catch (Exception e) {
e.printStackTrace();
}
}
8.ユーザーのApp右下上付き文字を変更します。
複数のサブユーザーが同じアプリケーションをインストールする場合は、マルチユーザを開いた後、彼らは(ソースコードにバッジと呼ばれる)右下の小さなに同じアイコンが表示されますので、我々は特定できない、我々は異なる別のユーザーは、右下の小さな表示を許可することができますアイコンは、デジタルアイコンは、我々は変更する方法を見て、良い選択です
frameworks/base/core/java/android/app/ApplicationPackageManager.java
getBadgeResIdForUser方法は、右下の小さな子供のAppユーザーにアイコンとして、DrawableのリソースIDを返します。
private int getBadgeResIdForUser(int userId) {
// Return the framework-provided badge.
if (isManagedProfile(userId)) {
return com.android.internal.R.drawable.ic_corp_icon_badge;
}
return 0;
}
このアイコンは、右下隅に小さなアイコンであり、そのときに大きなアイコンを行うには、アイコンを行い、透明の塗りつぶしに残りを表示するには、右下隅を立っています。ベクトル資産、サイズ64×64までのAndroidメーカーを導入し、SVG形式を生成するためのアイコンを行った後、インポートは、生成されたプロジェクトの解像度/描画可能描画可能リソースファイルで成功するリソースファイルを置き換えるためにframeworks/base/core/res/res/drawable/ic_corp_icon_badge.xml
、およびframeworks/base/core/res/res/values/symbols.xml
描画可能ファイルにステートメントを追加します
アプリケーションを開くには、タスクの最新リストでは9。
デフォルトでは、最新のタスクリストは、より多くの開いているアプリケーションを表示させるつもりはありません。
でframeworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
getRecentTasks方法、チェックがあります:
for (int i = 0; i < recentsCount && maxNum > 0; i++) {
TaskRecord tr = mRecentTasks.get(i);
//....
if (!tr.mUserSetupComplete) {
// Don't include task launched while user is not done setting-up.
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
"Skipping, user setup not complete: " + tr);
continue;
}
//....
res.add(rti);
//....
}
このチェックは、trがあり、コメントすることができframeworks/base/services/core/java/com/android/server/am/TaskRecord.java
、次のように割り当てられたクラスのインスタンス、mUserSetupComplete:
mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
USER_SETUP_COMPLETE, 0, userId) != 0;
10.タスクの最近の名前を開くアプリケーションを変更
サブデフォルトのユーザー名は「仕事」という言葉の最近の使命の適用前に追加されますあなたがそれらを非表示にする場合、言語は、英語は「仕事」と表示されますです
中文:
frameworks/base/core/res/res/values-zh-rCN/strings.xml
英文:
frameworks/base/core/res/res/values/strings.xml
変更managed_profile_label_badge
フィールドを、「仕事」や「仕事」を削除することができます。
アンロード時に11プロンプトのテキストを変更します。
メインのテキストをアンインストールするように促さよりオープンなアプリケーションであり、ユーザーは、変更する必要がある場合は、次のファイルを変更し、同じでない場合
中文:
パッケージ/アプリケーション/ PackageInstaller / RES /値-ZH-RCN /のstrings.xml
英文:
パッケージ/アプリケーション/ PackageInstaller / RES /値/のstrings.xml
変更しuninstall_application_text_user
たフィールドの値を