Dchaについて

ページ名:DchaService 及び DchaState について

DchaService はチャレンジパッドに搭載されているサービス。教材を動かすために必要不可欠なサービスとなっている。

通常rootやsystem権限が必要な機能なども提供されている。

テストアプリ

DchaServiceTester

dcha_state

これは学習環境や通常環境などを示す値で、以下のように定義されている

dcha_stateの値 説明
0 初期状態。com.android.settings.intelligence の検索結果から設定が開けるようになる

count_dcha_completed が在る場合。開発者向けオプションは開けない

1

セットアップウィザードを起動したときの値。

セットアップ中にホーム画面に戻ると、QuickStepが"1"である事を確認した後に DchaStateを"0"に戻し、ナビゲーションバーを表示させる。

2  
3

デジチャレモードと呼ばれている。

開発者向けオプションがパスワード無しで開ける。

count_dcha_completed が作成され、ブラウザとQSBと不明なソースからのアプリのインストールが無効化される。

変更方法

ADB

adb shell settings put system dcha_state [ 0 ~ 3 ]

BenesseExtension

android.os.BenesseExtension.setDchaState([ 0 ~ 3 ]);

使用できる関数

独自のパーミッション「jp.co.benesse.dcha.permission.ACCESS_SYSTEM」の使用で以下の関数を使用することができる

DchaService の外部から呼び出せる関数一覧

verifyUpdateImage

名前からupdate.zipの署名検証を行うように見えるがtrueを返すだけの関数になっている

strにはupdate.zipのパスを入れるが機能していない

public boolean verifyUpdateImage(String str) {
        Log.d("DchaService", "verifyUpdateImage 0001 updateFile:" + str);
        return true;
}

copyUpdateImage

/cacheにファイルをコピーする関数。通常system権限以上が必要だがその権限無しでコピー可能。

strにコピー元パス、str2にコピー先パスを入れる。str2は "/cache" で始まるパスでなければならない

public boolean copyUpdateImage(String str, String str2) {
    FileChannel channel;
    FileChannel channel2;
    Log.d("DchaService", "copyUpdateImage 0001 srcFile:" + str + " dstFile:" + ((String) str2));
    boolean z = false;
    if (TextUtils.isEmpty(str) || TextUtils.isEmpty(str2)) {
        Log.d("DchaService", "copyUpdateImage 0009");
        return false;
    } else if (!str2.startsWith("/cache")) {
        Log.d("DchaService", "copyUpdateImage 0010");
        return false;
    } else {
        FileChannel fileChannel = null;
        try {
            try {
                try {
                    File file = new File(str);
                    File file2 = new File((String) str2);
                    channel = new FileInputStream(file).getChannel();
                    try {
                        channel2 = new FileOutputStream(file2).getChannel();
                    } catch (FileNotFoundException e) {
                        e = e;
                        fileChannel = channel;
                        str2 = null;
                    } catch (IOException e2) {
                        e = e2;
                        fileChannel = channel;
                        str2 = null;
                    } catch (Exception e3) {
                        e = e3;
                        fileChannel = channel;
                        str2 = null;
                    } catch (Throwable th) {
                        th = th;
                        fileChannel = channel;
                        str2 = 0;
                    }
                } catch (IOException e4) {
                }
                try {
                    channel.transferTo(0L, channel.size(), channel2);
                    z = true;
                    Log.d("DchaService", "copyUpdateImage 0005");
                    if (channel != null) {
                        Log.d("DchaService", "copyUpdateImage 0006");
                        try {
                            channel.close();
                        } catch (IOException e5) {
                        }
                    }
                } catch (FileNotFoundException e6) {
                    str2 = channel2;
                    e = e6;
                    fileChannel = channel;
                    Log.e("DchaService", "copyUpdateImage 0002", e);
                    Log.d("DchaService", "copyUpdateImage 0005");
                    if (fileChannel != null) {
                        Log.d("DchaService", "copyUpdateImage 0006");
                        try {
                            fileChannel.close();
                        } catch (IOException e7) {
                        }
                    }
                    if (str2 != null) {
                        ?? r0 = "copyUpdateImage 0007";
                        Log.d("DchaService", "copyUpdateImage 0007");
                        str2.close();
                        fileChannel = r0;
                        str2 = str2;
                    }
                    Log.d("DchaService", "copyUpdateImage 0008 return:" + z);
                    return z;
                } catch (IOException e8) {
                    str2 = channel2;
                    e = e8;
                    fileChannel = channel;
                    Log.e("DchaService", "copyUpdateImage 0003", e);
                    Log.d("DchaService", "copyUpdateImage 0005");
                    if (fileChannel != null) {
                        Log.d("DchaService", "copyUpdateImage 0006");
                        try {
                            fileChannel.close();
                        } catch (IOException e9) {
                        }
                    }
                    if (str2 != null) {
                        ?? r02 = "copyUpdateImage 0007";
                        Log.d("DchaService", "copyUpdateImage 0007");
                        str2.close();
                        fileChannel = r02;
                        str2 = str2;
                    }
                    Log.d("DchaService", "copyUpdateImage 0008 return:" + z);
                    return z;
                } catch (Exception e10) {
                    str2 = channel2;
                    e = e10;
                    fileChannel = channel;
                    Log.e("DchaService", "copyUpdateImage 0004", e);
                    Log.d("DchaService", "copyUpdateImage 0005");
                    if (fileChannel != null) {
                        Log.d("DchaService", "copyUpdateImage 0006");
                        try {
                            fileChannel.close();
                        } catch (IOException e11) {
                        }
                    }
                    if (str2 != null) {
                        ?? r03 = "copyUpdateImage 0007";
                        Log.d("DchaService", "copyUpdateImage 0007");
                        str2.close();
                        fileChannel = r03;
                        str2 = str2;
                    }
                    Log.d("DchaService", "copyUpdateImage 0008 return:" + z);
                    return z;
                } catch (Throwable th2) {
                    str2 = channel2;
                    th = th2;
                    fileChannel = channel;
                    Log.d("DchaService", "copyUpdateImage 0005");
                    if (fileChannel != null) {
                        Log.d("DchaService", "copyUpdateImage 0006");
                        try {
                            fileChannel.close();
                        } catch (IOException e12) {
                        }
                    }
                    if (str2 != 0) {
                        Log.d("DchaService", "copyUpdateImage 0007");
                        try {
                            str2.close();
                        } catch (IOException e13) {
                        }
                    }
                    throw th;
                }
            } catch (FileNotFoundException e14) {
                e = e14;
                str2 = null;
            } catch (IOException e15) {
                e = e15;
                str2 = null;
            } catch (Exception e16) {
                e = e16;
                str2 = null;
            } catch (Throwable th3) {
                th = th3;
                str2 = 0;
            }
            if (channel2 != null) {
                String str3 = "DchaService";
                ?? r04 = "copyUpdateImage 0007";
                Log.d("DchaService", "copyUpdateImage 0007");
                channel2.close();
                fileChannel = r04;
                str2 = str3;
            }
            Log.d("DchaService", "copyUpdateImage 0008 return:" + z);
            return z;
        } catch (Throwable th4) {
            th = th4;
        }
    }
}

/cache 以外(/data など)にアクセスしたい場合は、/cache/../data のように、"/cache/../'からパスを指定する。

rebootPad

タブレットを再起動させる関数

i引数には再起動モード、strにはファイルパスを入れて使用する。

再起動モードはiの値に応じて変化し、0=通常再起動 1=初期化 2=パッケージのインストールを行う。

0, 1の場合は str に null を投げる。

public void rebootPad(int i, String str) throws RemoteException {
    Log.d("DchaService", "rebootPad 0001 rebootMode:" + i + " srcFile:" + str);
    try {
        PowerManager powerManager = (PowerManager) DchaService.this.getSystemService("power");
        switch (i) {
            case 0:
                Log.d("DchaService", "rebootPad 0002");
                powerManager.reboot(null);
                break;
            case 1:
                Log.d("DchaService", "rebootPad 0003");
                RecoverySystem.rebootWipeUserData(DchaService.this.getBaseContext());
                break;
            case 2:
                Log.d("DchaService", "rebootPad 0004");
                if (str != null) {
                    RecoverySystem.installPackage(DchaService.this.getBaseContext(), new File(str));
                    break;
                }
                break;
            default:
                Log.d("DchaService", "rebootPad 0005");
                break;
        }
        Log.d("DchaService", "rebootPad 0007");
    } catch (Exception e) {
        Log.e("DchaService", "rebootPad 0006", e);
        throw new RemoteException();
    }
}

setDefaultPreferredHomeApp

ホームアプリを設定する関数

str引数にはパッケージ名を入れる

public void setDefaultPreferredHomeApp(String str) throws RemoteException {
    try {
        Log.d("DchaService", "setDefalutPreferredHomeApp 0001 packageName:" + str);
        PackageManager packageManager = DchaService.this.getPackageManager();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_MAIN);
        intentFilter.addCategory(Intent.CATEGORY_HOME);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        List<ResolveInfo> queryIntentActivities = packageManager.queryIntentActivities(intent, 0);
        ArrayList arrayList = new ArrayList();
        ComponentName componentName = null;
        for (ResolveInfo resolveInfo : queryIntentActivities) {
            String str2 = resolveInfo.activityInfo.applicationInfo.packageName;
            String str3 = resolveInfo.activityInfo.name;
            Log.d("DchaService", "setDefalutPreferredHomeApp packName:" + str2);
            Log.d("DchaService", "setDefalutPreferredHomeApp activityName:" + str3);
            ComponentName componentName2 = new ComponentName(str2, str3);
            arrayList.add(componentName2);
            if (str2.equalsIgnoreCase(str)) {
                Log.d("DchaService", "setDefalutPreferredHomeApp 0002");
                Log.d("DchaService", "setDefalutPreferredHomeApp defaultHomeComponentName:" + ((Object) componentName2));
                componentName = componentName2;
            }
        }
        ComponentName[] componentNameArr = (ComponentName[]) arrayList.toArray(new ComponentName[arrayList.size()]);
        if (componentName != null) {
            Log.d("DchaService", "setDefalutPreferredHomeApp 0003");
            packageManager.addPreferredActivityAsUser(intentFilter, 1081344, componentNameArr, componentName, 0);
        }
        Log.d("DchaService", "setDefalutPreferredHomeApp 0005");
    } catch (Exception e) {
        Log.e("DchaService", "setDefalutPrefferredHomeApp 0004", e);
        throw new RemoteException(e.toString());
    }
}

clearDefaultPreferredApp

public void clearDefaultPreferredApp(String str) throws RemoteException {
    Log.d("DchaService", "clearDefaultPreferredApp 0001 packageName:" + str);
    try {
        DchaService.this.getPackageManager().clearPackagePreferredActivities(str);
    } catch (Exception e) {
        Log.e("DchaService", "clearDefaultPreferredApp 0002", e);
        throw new RemoteException(e.toString());
    }
}

disableADB

adbを無効にする関数

public void disableADB() {
    Log.d("DchaService", "disableADB 0001");
    Settings.Secure.putInt(DchaService.this.getContentResolver(), "adb_enabled", 0);
}

checkPadRooted

タブレットがroot化されているか確認する関数

false を返すだけなので、実際は意味無い。

public boolean checkPadRooted() throws RemoteException {
    Log.d("DchaService", "checkPadRooted 0001");
    return false;
}

installApp

アプリをインストールする関数。
Neo/Next では署名チェックが無いので使用できる。

strにapkファイルのパス、iには以下の数値を入れる

2=ダウングレードを許可 その他=ダウングレードを許可しない

public boolean installApp(String str, int i) throws RemoteException {
    HandlerThread handlerThread;
    Log.d("DchaService", "installApp 0001 path:" + str + " installFlag:" + i);
    try {
        try {
            PackageInstaller packageInstaller = DchaService.this.getPackageManager().getPackageInstaller();
            boolean z = true;
            PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(1);
            sessionParams.setInstallLocation(1);
            if (i != 2) {
                z = false;
            }
            sessionParams.setAllowDowngrade(z);
            int createSession = packageInstaller.createSession(sessionParams);
            PackageInstaller.Session openSession = packageInstaller.openSession(createSession);
            if (openSession == null) {
                Log.d("DchaService", "installApp 0002");
                return false;
            }
            handlerThread = new HandlerThread("installAppThread");
            try {
                handlerThread.start();
                Handler handler = new Handler(handlerThread.getLooper());
                PackageInstallSessionCallback packageInstallSessionCallback = new PackageInstallSessionCallback();
                packageInstaller.registerSessionCallback(packageInstallSessionCallback, handler);
                installAppSession(openSession, str);
                Intent intent = new Intent("jp.co.benesse.dcha.dchaservice.INSTALL_COMPLETE");
                intent.setPackage(DchaService.this.getPackageNameFromPid(Binder.getCallingPid()));
                openSession.commit(PendingIntent.getBroadcast(DchaService.this.getBaseContext(), createSession, intent, 0).getIntentSender());
                synchronized (packageInstallSessionCallback) {
                    while (!packageInstallSessionCallback.finished) {
                        try {
                            Log.d("DchaService", "installApp 0003");
                            packageInstallSessionCallback.wait();
                        } catch (InterruptedException e) {
                            Log.d("DchaService", "installApp 0004");
                        }
                    }
                }
                Log.d("DchaService", "installApp 0005");
                packageInstaller.unregisterSessionCallback(packageInstallSessionCallback);
                openSession.close();
                Log.d("DchaService", "installApp 0006");
                boolean z2 = packageInstallSessionCallback.result;
                Log.d("DchaService", "installApp 0008");
                handlerThread.quit();
                return z2;
            } catch (Exception e2) {
                e = e2;
                Log.e("DchaService", "installApp 0007", e);
                throw new RemoteException();
            } catch (Throwable th) {
                th = th;
                if (handlerThread != null) {
                    Log.d("DchaService", "installApp 0008");
                    handlerThread.quit();
                }
                throw th;
            }
        } catch (Exception e3) {
            e = e3;
        }
    } catch (Throwable th2) {
        th = th2;
        handlerThread = null;
    }
}

uninstallApp

アプリをアンインストールする関数

strにはパッケージ名を入れる。i2は不明。

public boolean uninstallApp(String str, int i) throws RuntimeException {
    Log.d("DchaService", "uninstallApp 0001 packageName:" + str + " uninstallFlag:" + i);
    try {
        String packageNameFromPid = DchaService.this.getPackageNameFromPid(getCallingPid());
        DchaService dchaService = DchaService.this;
        EmergencyLog.write(dchaService, "ELK002", str + " " + packageNameFromPid);
        PackageManager packageManager = DchaService.this.getPackageManager();
        int i2 = 2;
        if (i == 1) {
            Log.d("DchaService", "uninstallApp 0002");
            i2 = 3;
        } else {
            Log.d("DchaService", "uninstallApp 0003");
        }
        PackageDeleteObserver packageDeleteObserver = new PackageDeleteObserver();
        packageManager.deletePackage(str, packageDeleteObserver, i2);
        synchronized (packageDeleteObserver) {
            while (!packageDeleteObserver.finished) {
                try {
                    packageDeleteObserver.wait();
                } catch (InterruptedException e) {
                }
            }
        }
        Log.d("DchaService", "uninstallApp 0004");
        return packageDeleteObserver.result;
    } catch (Exception e2) {
        Log.e("DchaService", "uninstallApp 0005", e2);
        throw new RuntimeException();
    }
}

cancelSetup

セットアップをキャンセルする関数

public void cancelSetup() throws RemoteException {
    Log.d("DchaService", "cancelSetup 0001");
    DchaService.this.doCancelDigichalized();
}

setSetupStatus

DchaStateと環境変数のDigichalizedStatusを変更する関数

public void setSetupStatus(int i) {
    Log.d("DchaService", "setSetupStatus 0001 status:" + i);
    PreferenceManager.getDefaultSharedPreferences(DchaService.this).edit().putInt("DigichalizedStatus", i).commit();
    Settings.System.putInt(DchaService.this.getContentResolver(), "dcha_state", i);
}

getSetupStatus

DigichalizedStatusを取得する関数

public int getSetupStatus() {
    Log.d("DchaService", "getSetupStatus 0001");
    int i = PreferenceManager.getDefaultSharedPreferences(DchaService.this).getInt("DigichalizedStatus", -1);
    Log.d("DchaService", "getSetupStatus 0002 return:" + i);
    return i;
}

setSystemTime

removeTask

sdUnmount

setDefaultParam

getForegroundPackageName

copyFile

外部ストレージにファイルをコピーする関数。相対パスを受け付けずディレクトリトラバーサルができないようにされている。

strがコピー元、str2がコピー先のパス

public boolean copyFile(String str, String str2) throws RemoteException {
    boolean z;
    String canonicalExternalPath;
    Log.d("DchaService", "copyFile 0001 srcFilePath:" + str + " dstFilePath:" + str2);
    try {
        canonicalExternalPath = getCanonicalExternalPath(System.getenv("SECONDARY_STORAGE"));
    } catch (Exception e) {
        Log.e("DchaService", "copyFile 0006", e);
        z = false;
    }
    if (TextUtils.isEmpty(str) || TextUtils.isEmpty(str2)) {
        Log.d("DchaService", "copyFile 0002");
        throw new IllegalArgumentException();
    }
    String canonicalExternalPath2 = getCanonicalExternalPath(str);
    String canonicalExternalPath3 = getCanonicalExternalPath(str2);
    if (!canonicalExternalPath2.startsWith(canonicalExternalPath) && !canonicalExternalPath3.startsWith(canonicalExternalPath)) {
        Log.d("DchaService", "copyFile 0003");
        throw new SecurityException("The path is not a external storage.");
    }
    File file = new File(canonicalExternalPath2);
    File file2 = new File(canonicalExternalPath3);
    if (file.isFile() && (file2.isDirectory() || file2.isFile() || (!file2.exists() && file2.getParentFile().isDirectory()))) {
        Log.d("DchaService", "copyFile 0004");
        z = fileCopy(file, file2);
        Log.d("DchaService", "copyFile 0007 result:" + z);
        return z;
    }
    Log.d("DchaService", "copyFile 0005");
    throw new IllegalArgumentException();
}

deleteFile

getUserCount

isDeviceEncryptionEnabled

hideNavigationBar

"true" で非表示、"false" で表示

setPermissionEnforced

シェアボタン: このページをSNSに投稿するのに便利です。

コメント

返信元返信をやめる

※ 悪質なユーザーの書き込みは制限します。

最新を表示する

NG表示方式

NGID一覧