Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8f72d24
Manager に SettingProfile (空実装) を新規追加。
masaru-takano Apr 28, 2020
477f2ed
Merge branch 'master' into feature_copyguard_api
masaru-takano May 14, 2020
d7ce5e8
コピー防止の状態取得・有効化・無効化の API を実装。プロファイル名を変更: CopyGuard → CopyProtection。
masaru-takano May 15, 2020
d3ae793
開発者向けオプション表示前に確認ダイアログを表示。Android 10 以降では Activity は通知経由で起動。
masaru-takano May 18, 2020
962eb84
コピー防止の状態変更イベント API を実装。
masaru-takano May 19, 2020
4ddb386
重複したイベントを送信しないように修正。
masaru-takano May 20, 2020
c128fa3
「コピーガード」の英語を CopyGuard に統一。
masaru-takano May 20, 2020
6515acf
ライセンス文を追記。
masaru-takano May 22, 2020
c2ba6c4
著作権保護機能の後始末処理を実装。
masaru-takano Jun 9, 2020
c57be48
Merge pull request #683 from TakayukiHoshi1984/modify_switchbot_security
TakayukiHoshi1984 Aug 17, 2020
d206979
Merge pull request #684 from TakayukiHoshi1984/modify_switchbot_security
TakayukiHoshi1984 Aug 17, 2020
eb7d787
Managerのライフサイクルに合わせてコピーガード機能の後始末処理を実行。
masaru-takano Sep 17, 2020
6b9082f
コピーガード状態変更イベントの解除に失敗する不具合を修正。
masaru-takano Sep 17, 2020
5a1ac16
不要な処理を削除。コメントの誤字修正。
masaru-takano Sep 17, 2020
bb9d692
Merge remote-tracking branch 'origin/main' into feature_copyright_pro…
masaru-takano Sep 18, 2020
61d8454
有効化の処理を順番に実行する。
masaru-takano Sep 18, 2020
6ccced5
権限許可画面をアプリ履歴に残さない。オーバーレイを複数追加させない。
masaru-takano Sep 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class OverlayPermissionActivity extends Activity implements SimpleDialogF
private static final int REQUEST_CODE_OVERLAY = 1234;

/**
* オーバーレイ許可設定画面を表示して良いかの確認ダイアンログのタグを定義.
* オーバーレイ許可設定画面を表示して良いかの確認ダイアログのタグを定義.
*/
private static final String TAG_NO_PERMISSION_DIALOG = "overlay-permission";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,20 @@
android:exported="false"
android:taskAffinity=".permission"
android:theme="@style/Theme.Dialog.Transparent"/>

<!-- コピーガード用オーバーレイ許可取得画面 -->
<activity android:name=".protection.OverlayPermissionActivity"
android:exported="false"
android:excludeFromRecents="true"
android:taskAffinity=".permission"
android:theme="@style/Theme.Dialog.Transparent"/>

<!-- 開発者向けオプション表示確認画面 -->
<activity android:name=".protection.DeveloperToolDialogActivity"
android:exported="false"
android:excludeFromRecents="true"
android:taskAffinity=".permission"
android:theme="@style/Theme.Dialog.Transparent"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.deviceconnect.android.manager.core.plugin.MessagingException;
import org.deviceconnect.android.manager.core.util.DConnectUtil;
import org.deviceconnect.android.manager.core.util.VersionName;
import org.deviceconnect.android.manager.profile.DConnectSettingProfile;
import org.deviceconnect.android.manager.setting.KeywordDialogActivity;
import org.deviceconnect.android.manager.setting.SettingActivity;
import org.deviceconnect.android.manager.util.NotificationUtil;
Expand Down Expand Up @@ -91,6 +92,11 @@ public class DConnectService extends Service {
*/
private DConnectManager mManager;

/**
* Device Connect Manager 本体に設定する Setting プロファイル.
*/
private DConnectSettingProfile mSettingProfile;

/**
* WakeLockのインスタンス.
*/
Expand Down Expand Up @@ -132,6 +138,8 @@ public void onCreate() {

DConnectApplication app = (DConnectApplication) getApplication();
mSettings = app.getSettings();
mSettingProfile = new DConnectSettingProfile();
mSettingProfile.start(this, R.drawable.on_icon);
mManager = new DConnectManager(this, mSettings, app.getPluginManager()) {
@Override
public Class<? extends BroadcastReceiver> getDConnectBroadcastReceiverClass() {
Expand All @@ -148,6 +156,7 @@ public Class<? extends Activity> getKeywordActivityClass() {
return SettingActivity.class;
}
};
mManager.addProfile(mSettingProfile);

// Webサーバの起動フラグがONになっている場合には起動を行う
if (mSettings.isManagerStartFlag()) {
Expand Down Expand Up @@ -190,6 +199,7 @@ public int onStartCommand(final Intent intent, final int flags, final int startI
@Override
public void onDestroy() {
stopInternal();
mSettingProfile.stop();
mManager = null;
super.onDestroy();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
DConnectSettingProfile.java
Copyright (c) 2020 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.manager.profile;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import org.deviceconnect.android.event.Event;
import org.deviceconnect.android.event.EventError;
import org.deviceconnect.android.event.EventManager;
import org.deviceconnect.android.manager.protection.SimpleCopyGuard;
import org.deviceconnect.android.message.MessageUtils;
import org.deviceconnect.android.profile.DConnectProfile;
import org.deviceconnect.android.profile.api.DeleteApi;
import org.deviceconnect.android.profile.api.GetApi;
import org.deviceconnect.android.profile.api.PutApi;
import org.deviceconnect.message.DConnectMessage;
import org.deviceconnect.message.intent.message.IntentDConnectMessage;

import java.util.List;

import static org.deviceconnect.android.manager.BuildConfig.DEBUG;

/**
* Setting プロファイル.
*
* @author NTT DOCOMO, INC.
*/
public class DConnectSettingProfile extends DConnectProfile {

/**
* インターフェース名: copyGuard
*/
private static final String INTERFACE_COPY_GUARD = "copyGuard";

/**
* アトリビュート名: onChange
*/
private static final String ATTR_ON_CHANGE = "onChange";

/**
* コピーガード機能管理クラス.
*/
private SimpleCopyGuard mCopyGuard;

/**
* コピーガード機能のイベントを受信するスレッド.
*/
private HandlerThread mHandlerThread;

private static Intent createEventMessage(final Event event) {
Intent message = MessageUtils.createEventIntent();
message.putExtra(DConnectMessage.EXTRA_SERVICE_ID, event.getServiceId());
message.putExtra(DConnectMessage.EXTRA_PROFILE, event.getProfile());
message.putExtra(DConnectMessage.EXTRA_INTERFACE, event.getInterface());
message.putExtra(DConnectMessage.EXTRA_ATTRIBUTE, event.getAttribute());
message.putExtra(DConnectMessage.EXTRA_ACCESS_TOKEN, event.getAccessToken());
String receiverName = event.getReceiverName();
if (receiverName != null) {
ComponentName cn = ComponentName.unflattenFromString(receiverName);
message.setComponent(cn);
}
return message;
}

public DConnectSettingProfile() {
// GET /gotapi/setting/copyGuard
addApi(new GetApi() {
@Override
public String getAttribute() {
return "copyGuard";
}

@Override
public boolean onRequest(final Intent request, final Intent response) {
setResult(response, DConnectMessage.RESULT_OK);
response.putExtra("enabled", mCopyGuard.isEnabled());
return true;
}
});

// PUT /gotapi/setting/copyGuard
addApi(new PutApi() {
@Override
public String getAttribute() {
return "copyGuard";
}

@Override
public boolean onRequest(final Intent request, final Intent response) {
try {
mCopyGuard.enable();
setResult(response, DConnectMessage.RESULT_OK);
return true;
} catch (Throwable e) {
MessageUtils.setUnknownError(response, "Failed to enable copy guard: " + e.getMessage());
return true;
}
}
});

// DELETE /gotapi/setting/copyGuard
addApi(new DeleteApi() {
@Override
public String getAttribute() {
return "copyGuard";
}

@Override
public boolean onRequest(final Intent request, final Intent response) {
mCopyGuard.disable();
setResult(response, DConnectMessage.RESULT_OK);
return true;
}
});

// PUT /gotapi/setting/copyGuard/onChange
addApi(new PutApi() {
@Override
public String getInterface() {
return "copyGuard";
}

@Override
public String getAttribute() {
return "onChange";
}

@Override
public boolean onRequest(final Intent request, final Intent response) {
if (DEBUG) {
Log.d("ABC", "PUT /gotapi/setting/copyGuard/onChange: receiver = " + request.getParcelableExtra("receiver"));
}

setReceiverNameToRequest(request);
EventError error = EventManager.INSTANCE.addEvent(request);
switch (error) {
case NONE:
setResult(response, DConnectMessage.RESULT_OK);
break;
case INVALID_PARAMETER:
MessageUtils.setInvalidRequestParameterError(response);
break;
default:
MessageUtils.setUnknownError(response);
break;
}
return true;
}
});

// DELETE /gotapi/setting/copyGuard/onChange
addApi(new DeleteApi() {
@Override
public String getInterface() {
return "copyGuard";
}

@Override
public String getAttribute() {
return "onChange";
}

@Override
public boolean onRequest(final Intent request, final Intent response) {
setReceiverNameToRequest(request);
EventError error = EventManager.INSTANCE.removeEvent(request);
switch (error) {
case NONE:
setResult(response, DConnectMessage.RESULT_OK);
break;
case INVALID_PARAMETER:
MessageUtils.setInvalidRequestParameterError(response);
break;
case NOT_FOUND:
MessageUtils.setUnknownError(response, "Event is not registered.");
break;
default:
MessageUtils.setUnknownError(response);
break;
}
return true;
}
});
}

private void setReceiverNameToRequest(final Intent request) {
// NOTE: プラグインSDK側でレシーバー名が設定されないことが考慮されていないため、
// 暫定的措置として擬似的なレシーバー名を設定する.
request.putExtra(IntentDConnectMessage.EXTRA_RECEIVER,
new ComponentName(getContext(), "org.deviceconnect.android.manager.DConnectBroadcastReceiver"));
}

public void start(final Context context, final int appIconId) {
mHandlerThread = new HandlerThread("SettingProfileThread");
mHandlerThread.start();
mCopyGuard = new SimpleCopyGuard(context, appIconId);
mCopyGuard.setEventListener(((setting, isEnabled) -> {
List<Event> events = EventManager.INSTANCE.getEventList(null,
getProfileName(),
INTERFACE_COPY_GUARD,
ATTR_ON_CHANGE);
for (Event event : events) {
Intent intent = createEventMessage(event);
intent.putExtra("enabled", isEnabled);
sendEvent(intent, event.getAccessToken());
}
}), new Handler(mHandlerThread.getLooper()));
}

public void stop() {
mCopyGuard.reset();
mCopyGuard = null;
mHandlerThread.quitSafely();
mHandlerThread = null;
}

@Override
public String getProfileName() {
return "setting";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
CopyGuardSetting.java
Copyright (c) 2020 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.manager.protection;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;

import org.deviceconnect.android.manager.R;
import org.deviceconnect.android.util.NotificationUtils;

/**
* コピーガード設定の基底クラス.
*
* @author NTT DOCOMO, INC.
*/
public abstract class CopyGuardSetting {

public interface EventListener {
void onSettingChange(CopyGuardSetting setting, boolean isEnabled);
}

protected EventListener mEventListener;

public abstract boolean isAvailable();

public abstract boolean isEnabled();

public abstract void enable();

public abstract void disable();

public void reset() {
}

public void setEventListener(final EventListener listener, final Handler handler) {
mEventListener = new EventListenerHolder(listener, handler);
}

protected void startActivity(final Context context,
final Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
NotificationUtils.createNotificationChannel(context);
NotificationUtils.notify(context, hashCode(), 0, intent,
context.getString(R.string.copy_guard_notification_activity_warnning));
} else {
context.startActivity(intent);
}
}

protected void notifyOnSettingChange(final boolean isEnabled) {
if (mEventListener != null) {
mEventListener.onSettingChange(this, isEnabled);
}
}

private static class EventListenerHolder implements EventListener {
private final EventListener mEventListener;
private final Handler mHandler;

EventListenerHolder(final EventListener eventListener,
final Handler handler) {
mEventListener = eventListener;
mHandler = handler;
}

@Override
public void onSettingChange(final CopyGuardSetting setting, final boolean isEnabled) {
mHandler.post(() -> mEventListener.onSettingChange(setting, isEnabled));
}
}
}
Loading