1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings.deviceinfo;
18
19import android.annotation.Nullable;
20import android.app.Activity;
21import android.app.ActivityManager;
22import android.app.AlertDialog;
23import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.graphics.drawable.Drawable;
29import android.graphics.PorterDuff;
30import android.hardware.usb.UsbManager;
31import android.os.Bundle;
32import android.os.UserHandle;
33import android.os.UserManager;
34import android.view.LayoutInflater;
35import android.view.View;
36import android.view.View.OnClickListener;
37import android.widget.Checkable;
38import android.widget.LinearLayout;
39import android.widget.TextView;
40
41import com.android.settings.R;
42import com.android.settingslib.RestrictedLockUtils;
43
44import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
45
46/**
47 * UI for the USB chooser dialog.
48 *
49 */
50public class UsbModeChooserActivity extends Activity {
51
52    public static final int[] DEFAULT_MODES = {
53        UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE,
54        UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE,
55        UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP,
56        UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP,
57        UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI
58    };
59
60    private UsbBackend mBackend;
61    private AlertDialog mDialog;
62    private LayoutInflater mLayoutInflater;
63    private EnforcedAdmin mEnforcedAdmin;
64
65    private BroadcastReceiver mDisconnectedReceiver = new BroadcastReceiver() {
66        @Override
67        public void onReceive(Context context, Intent intent) {
68            String action = intent.getAction();
69            if (UsbManager.ACTION_USB_STATE.equals(action)) {
70                boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
71                boolean hostConnected =
72                        intent.getBooleanExtra(UsbManager.USB_HOST_CONNECTED, false);
73                if (!connected && !hostConnected) {
74                    mDialog.dismiss();
75                }
76            }
77        }
78    };
79
80    @Override
81    protected void onCreate(@Nullable Bundle savedInstanceState) {
82
83        super.onCreate(savedInstanceState);
84
85        mLayoutInflater = LayoutInflater.from(this);
86
87        mDialog = new AlertDialog.Builder(this)
88                .setTitle(R.string.usb_use)
89                .setView(R.layout.usb_dialog_container)
90                .setOnDismissListener(new DialogInterface.OnDismissListener() {
91                    @Override
92                    public void onDismiss(DialogInterface dialog) {
93                        finish();
94                    }
95                })
96                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
97                    @Override
98                    public void onClick(DialogInterface dialog, int which) {
99                        finish();
100                    }
101                }).create();
102        mDialog.show();
103
104        LinearLayout container = (LinearLayout) mDialog.findViewById(R.id.container);
105
106        mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(this,
107                UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.myUserId());
108        mBackend = new UsbBackend(this);
109        int current = mBackend.getCurrentMode();
110        for (int i = 0; i < DEFAULT_MODES.length; i++) {
111            if (mBackend.isModeSupported(DEFAULT_MODES[i])
112                    && !mBackend.isModeDisallowedBySystem(DEFAULT_MODES[i])) {
113                inflateOption(DEFAULT_MODES[i], current == DEFAULT_MODES[i], container,
114                        mBackend.isModeDisallowed(DEFAULT_MODES[i]));
115            }
116        }
117    }
118
119    @Override
120    public void onStart() {
121        super.onStart();
122
123        IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
124        registerReceiver(mDisconnectedReceiver, filter);
125    }
126
127    @Override
128    protected void onStop() {
129        unregisterReceiver(mDisconnectedReceiver);
130        super.onStop();
131    }
132
133    private void inflateOption(final int mode, boolean selected, LinearLayout container,
134            final boolean disallowedByAdmin) {
135        View v = mLayoutInflater.inflate(R.layout.restricted_radio_with_summary, container, false);
136
137        TextView titleView = (TextView) v.findViewById(android.R.id.title);
138        titleView.setText(getTitle(mode));
139        TextView summaryView = (TextView) v.findViewById(android.R.id.summary);
140        summaryView.setText(getSummary(mode));
141
142        if (disallowedByAdmin) {
143            if (mEnforcedAdmin != null) {
144                setDisabledByAdmin(v, titleView, summaryView);
145            } else {
146                return;
147            }
148        }
149
150        v.setOnClickListener(new OnClickListener() {
151            @Override
152            public void onClick(View v) {
153                if (disallowedByAdmin && mEnforcedAdmin != null) {
154                    RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
155                            UsbModeChooserActivity.this, mEnforcedAdmin);
156                    return;
157                }
158                if (!ActivityManager.isUserAMonkey()) {
159                    mBackend.setMode(mode);
160                }
161                mDialog.dismiss();
162                finish();
163            }
164        });
165        ((Checkable) v).setChecked(selected);
166        container.addView(v);
167    }
168
169    private void setDisabledByAdmin(View rootView, TextView titleView, TextView summaryView) {
170        if (mEnforcedAdmin != null) {
171            titleView.setEnabled(false);
172            summaryView.setEnabled(false);
173            rootView.findViewById(R.id.restricted_icon).setVisibility(View.VISIBLE);
174            Drawable[] compoundDrawables = titleView.getCompoundDrawablesRelative();
175            compoundDrawables[0 /* start */].mutate().setColorFilter(
176                    getColor(R.color.disabled_text_color), PorterDuff.Mode.MULTIPLY);
177        }
178    }
179
180    private static int getSummary(int mode) {
181        switch (mode) {
182            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE:
183                return R.string.usb_use_charging_only_desc;
184            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE:
185                return R.string.usb_use_power_only_desc;
186            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP:
187                return R.string.usb_use_file_transfers_desc;
188            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP:
189                return R.string.usb_use_photo_transfers_desc;
190            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI:
191                return R.string.usb_use_MIDI_desc;
192        }
193        return 0;
194    }
195
196    private static int getTitle(int mode) {
197        switch (mode) {
198            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE:
199                return R.string.usb_use_charging_only;
200            case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE:
201                return R.string.usb_use_power_only;
202            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP:
203                return R.string.usb_use_file_transfers;
204            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP:
205                return R.string.usb_use_photo_transfers;
206            case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI:
207                return R.string.usb_use_MIDI;
208        }
209        return 0;
210    }
211}
212