From 38e932b37aea8d2f6866c3c879afa188587bcde3 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 7 Jul 2015 15:35:22 -0700 Subject: Move NetworkPolicyEditor from Settings packge to settingslib. Change-Id: Ibed9b9dabae42a71d77f493fedc3ab1c4343597f --- .../android/settingslib/NetworkPolicyEditor.java | 254 +++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java (limited to 'packages/SettingsLib') diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java new file mode 100644 index 0000000..cf08f50 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib; + +import static android.net.NetworkPolicy.CYCLE_NONE; +import static android.net.NetworkPolicy.LIMIT_DISABLED; +import static android.net.NetworkPolicy.SNOOZE_NEVER; +import static android.net.NetworkPolicy.WARNING_DISABLED; +import static android.net.NetworkTemplate.MATCH_WIFI; +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.net.NetworkPolicy; +import android.net.NetworkPolicyManager; +import android.net.NetworkTemplate; +import android.net.wifi.WifiInfo; +import android.os.AsyncTask; +import android.text.TextUtils; +import android.text.format.Time; + +import com.google.android.collect.Lists; + +import java.util.ArrayList; + +/** + * Utility class to modify list of {@link NetworkPolicy}. Specifically knows + * about which policies can coexist. This editor offers thread safety when + * talking with {@link NetworkPolicyManager}. + * + * @hide + */ +public class NetworkPolicyEditor { + // TODO: be more robust when missing policies from service + + public static final boolean ENABLE_SPLIT_POLICIES = false; + + private NetworkPolicyManager mPolicyManager; + private ArrayList mPolicies = Lists.newArrayList(); + + public NetworkPolicyEditor(NetworkPolicyManager policyManager) { + mPolicyManager = checkNotNull(policyManager); + } + + public void read() { + final NetworkPolicy[] policies = mPolicyManager.getNetworkPolicies(); + + boolean modified = false; + mPolicies.clear(); + for (NetworkPolicy policy : policies) { + // TODO: find better place to clamp these + if (policy.limitBytes < -1) { + policy.limitBytes = LIMIT_DISABLED; + modified = true; + } + if (policy.warningBytes < -1) { + policy.warningBytes = WARNING_DISABLED; + modified = true; + } + + mPolicies.add(policy); + } + + // when we cleaned policies above, write back changes + if (modified) writeAsync(); + } + + public void writeAsync() { + // TODO: consider making more robust by passing through service + final NetworkPolicy[] policies = mPolicies.toArray(new NetworkPolicy[mPolicies.size()]); + new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + write(policies); + return null; + } + }.execute(); + } + + public void write(NetworkPolicy[] policies) { + mPolicyManager.setNetworkPolicies(policies); + } + + public boolean hasLimitedPolicy(NetworkTemplate template) { + final NetworkPolicy policy = getPolicy(template); + return policy != null && policy.limitBytes != LIMIT_DISABLED; + } + + public NetworkPolicy getOrCreatePolicy(NetworkTemplate template) { + NetworkPolicy policy = getPolicy(template); + if (policy == null) { + policy = buildDefaultPolicy(template); + mPolicies.add(policy); + } + return policy; + } + + public NetworkPolicy getPolicy(NetworkTemplate template) { + for (NetworkPolicy policy : mPolicies) { + if (policy.template.equals(template)) { + return policy; + } + } + return null; + } + + public NetworkPolicy getPolicyMaybeUnquoted(NetworkTemplate template) { + NetworkPolicy policy = getPolicy(template); + if (policy != null) { + return policy; + } else { + return getPolicy(buildUnquotedNetworkTemplate(template)); + } + } + + @Deprecated + private static NetworkPolicy buildDefaultPolicy(NetworkTemplate template) { + // TODO: move this into framework to share with NetworkPolicyManagerService + final int cycleDay; + final String cycleTimezone; + final boolean metered; + + if (template.getMatchRule() == MATCH_WIFI) { + cycleDay = CYCLE_NONE; + cycleTimezone = Time.TIMEZONE_UTC; + metered = false; + } else { + final Time time = new Time(); + time.setToNow(); + cycleDay = time.monthDay; + cycleTimezone = time.timezone; + metered = true; + } + + return new NetworkPolicy(template, cycleDay, cycleTimezone, WARNING_DISABLED, + LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, metered, true); + } + + public int getPolicyCycleDay(NetworkTemplate template) { + final NetworkPolicy policy = getPolicy(template); + return (policy != null) ? policy.cycleDay : -1; + } + + public void setPolicyCycleDay(NetworkTemplate template, int cycleDay, String cycleTimezone) { + final NetworkPolicy policy = getOrCreatePolicy(template); + policy.cycleDay = cycleDay; + policy.cycleTimezone = cycleTimezone; + policy.inferred = false; + policy.clearSnooze(); + writeAsync(); + } + + public long getPolicyWarningBytes(NetworkTemplate template) { + final NetworkPolicy policy = getPolicy(template); + return (policy != null) ? policy.warningBytes : WARNING_DISABLED; + } + + public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) { + final NetworkPolicy policy = getOrCreatePolicy(template); + policy.warningBytes = warningBytes; + policy.inferred = false; + policy.clearSnooze(); + writeAsync(); + } + + public long getPolicyLimitBytes(NetworkTemplate template) { + final NetworkPolicy policy = getPolicy(template); + return (policy != null) ? policy.limitBytes : LIMIT_DISABLED; + } + + public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) { + final NetworkPolicy policy = getOrCreatePolicy(template); + policy.limitBytes = limitBytes; + policy.inferred = false; + policy.clearSnooze(); + writeAsync(); + } + + public boolean getPolicyMetered(NetworkTemplate template) { + NetworkPolicy policy = getPolicy(template); + if (policy != null) { + return policy.metered; + } else { + return false; + } + } + + public void setPolicyMetered(NetworkTemplate template, boolean metered) { + boolean modified = false; + + NetworkPolicy policy = getPolicy(template); + if (metered) { + if (policy == null) { + policy = buildDefaultPolicy(template); + policy.metered = true; + policy.inferred = false; + mPolicies.add(policy); + modified = true; + } else if (!policy.metered) { + policy.metered = true; + policy.inferred = false; + modified = true; + } + + } else { + if (policy == null) { + // ignore when policy doesn't exist + } else if (policy.metered) { + policy.metered = false; + policy.inferred = false; + modified = true; + } + } + + // Remove legacy unquoted policies while we're here + final NetworkTemplate unquoted = buildUnquotedNetworkTemplate(template); + final NetworkPolicy unquotedPolicy = getPolicy(unquoted); + if (unquotedPolicy != null) { + mPolicies.remove(unquotedPolicy); + modified = true; + } + + if (modified) writeAsync(); + } + + /** + * Build a revised {@link NetworkTemplate} that matches the same rule, but + * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work + * around legacy bugs. + */ + private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) { + if (template == null) return null; + final String networkId = template.getNetworkId(); + final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId); + if (!TextUtils.equals(strippedNetworkId, networkId)) { + return new NetworkTemplate( + template.getMatchRule(), template.getSubscriberId(), strippedNetworkId); + } else { + return null; + } + } +} -- cgit v1.1 From c4a4064c1297dc879d64b0bae198e903b9a6fc9a Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 13 Jul 2015 10:55:29 -0700 Subject: Move AppItem, ChartData, ChartDataLoader from Settings to SettingsLib. Change-Id: I1a3b245aafc5a69a13420338385c932b8fa176c1 --- .../src/com/android/settingslib/AppItem.java | 85 ++++++++++++ .../src/com/android/settingslib/net/ChartData.java | 27 ++++ .../android/settingslib/net/ChartDataLoader.java | 145 +++++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 packages/SettingsLib/src/com/android/settingslib/AppItem.java create mode 100644 packages/SettingsLib/src/com/android/settingslib/net/ChartData.java create mode 100644 packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java (limited to 'packages/SettingsLib') diff --git a/packages/SettingsLib/src/com/android/settingslib/AppItem.java b/packages/SettingsLib/src/com/android/settingslib/AppItem.java new file mode 100644 index 0000000..1729e09 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/AppItem.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.SparseBooleanArray; + +public class AppItem implements Comparable, Parcelable { + public static final int CATEGORY_USER = 0; + public static final int CATEGORY_APP_TITLE = 1; + public static final int CATEGORY_APP = 2; + + public final int key; + public boolean restricted; + public int category; + + public SparseBooleanArray uids = new SparseBooleanArray(); + public long total; + + public AppItem() { + this.key = 0; + } + + public AppItem(int key) { + this.key = key; + } + + public AppItem(Parcel parcel) { + key = parcel.readInt(); + uids = parcel.readSparseBooleanArray(); + total = parcel.readLong(); + } + + public void addUid(int uid) { + uids.put(uid, true); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(key); + dest.writeSparseBooleanArray(uids); + dest.writeLong(total); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public int compareTo(AppItem another) { + int comparison = Integer.compare(category, another.category); + if (comparison == 0) { + comparison = Long.compare(another.total, total); + } + return comparison; + } + + public static final Creator CREATOR = new Creator() { + @Override + public AppItem createFromParcel(Parcel in) { + return new AppItem(in); + } + + @Override + public AppItem[] newArray(int size) { + return new AppItem[size]; + } + }; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java new file mode 100644 index 0000000..e30aac5 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.net; + +import android.net.NetworkStatsHistory; + +public class ChartData { + public NetworkStatsHistory network; + + public NetworkStatsHistory detail; + public NetworkStatsHistory detailDefault; + public NetworkStatsHistory detailForeground; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java new file mode 100644 index 0000000..223c055 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.net; + +import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStatsHistory.FIELD_RX_BYTES; +import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; +import static android.text.format.DateUtils.HOUR_IN_MILLIS; + +import android.content.AsyncTaskLoader; +import android.content.Context; +import android.net.INetworkStatsSession; +import android.net.NetworkStatsHistory; +import android.net.NetworkTemplate; +import android.os.Bundle; +import android.os.RemoteException; + +import com.android.settingslib.AppItem; + +/** + * Loader for historical chart data for both network and UID details. + */ +public class ChartDataLoader extends AsyncTaskLoader { + private static final String KEY_TEMPLATE = "template"; + private static final String KEY_APP = "app"; + private static final String KEY_FIELDS = "fields"; + + private final INetworkStatsSession mSession; + private final Bundle mArgs; + + public static Bundle buildArgs(NetworkTemplate template, AppItem app) { + return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES); + } + + public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) { + final Bundle args = new Bundle(); + args.putParcelable(KEY_TEMPLATE, template); + args.putParcelable(KEY_APP, app); + args.putInt(KEY_FIELDS, fields); + return args; + } + + public ChartDataLoader(Context context, INetworkStatsSession session, Bundle args) { + super(context); + mSession = session; + mArgs = args; + } + + @Override + protected void onStartLoading() { + super.onStartLoading(); + forceLoad(); + } + + @Override + public ChartData loadInBackground() { + final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE); + final AppItem app = mArgs.getParcelable(KEY_APP); + final int fields = mArgs.getInt(KEY_FIELDS); + + try { + return loadInBackground(template, app, fields); + } catch (RemoteException e) { + // since we can't do much without history, and we don't want to + // leave with half-baked UI, we bail hard. + throw new RuntimeException("problem reading network stats", e); + } + } + + private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields) + throws RemoteException { + final ChartData data = new ChartData(); + data.network = mSession.getHistoryForNetwork(template, fields); + + if (app != null) { + // load stats for current uid and template + final int size = app.uids.size(); + for (int i = 0; i < size; i++) { + final int uid = app.uids.keyAt(i); + data.detailDefault = collectHistoryForUid( + template, uid, SET_DEFAULT, data.detailDefault); + data.detailForeground = collectHistoryForUid( + template, uid, SET_FOREGROUND, data.detailForeground); + } + + if (size > 0) { + data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration()); + data.detail.recordEntireHistory(data.detailDefault); + data.detail.recordEntireHistory(data.detailForeground); + } else { + data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS); + data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS); + data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS); + } + } + + return data; + } + + @Override + protected void onStopLoading() { + super.onStopLoading(); + cancelLoad(); + } + + @Override + protected void onReset() { + super.onReset(); + cancelLoad(); + } + + /** + * Collect {@link NetworkStatsHistory} for the requested UID, combining with + * an existing {@link NetworkStatsHistory} if provided. + */ + private NetworkStatsHistory collectHistoryForUid( + NetworkTemplate template, int uid, int set, NetworkStatsHistory existing) + throws RemoteException { + final NetworkStatsHistory history = mSession.getHistoryForUid( + template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES); + + if (existing != null) { + existing.recordEntireHistory(history); + return existing; + } else { + return history; + } + } +} -- cgit v1.1 From c0b99c9a248ed2e3e86688465df15690f65d0d4a Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 20 Aug 2015 22:34:49 -0700 Subject: Move SummaryForAllUidLoader to SettingsLib. In order to show the data usage per app on Android Wear, I'm moving SummaryForAllUidLoader to SettingsLib so that the code can be reused. Change-Id: I4819ee96a75d62a86968376556258270b3bb8ba1 --- .../settingslib/net/SummaryForAllUidLoader.java | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java (limited to 'packages/SettingsLib') diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java new file mode 100644 index 0000000..572bae1 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.net; + +import android.content.AsyncTaskLoader; +import android.content.Context; +import android.net.INetworkStatsSession; +import android.net.NetworkStats; +import android.net.NetworkTemplate; +import android.os.Bundle; +import android.os.RemoteException; + +public class SummaryForAllUidLoader extends AsyncTaskLoader { + private static final String KEY_TEMPLATE = "template"; + private static final String KEY_START = "start"; + private static final String KEY_END = "end"; + + private final INetworkStatsSession mSession; + private final Bundle mArgs; + + public static Bundle buildArgs(NetworkTemplate template, long start, long end) { + final Bundle args = new Bundle(); + args.putParcelable(KEY_TEMPLATE, template); + args.putLong(KEY_START, start); + args.putLong(KEY_END, end); + return args; + } + + public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) { + super(context); + mSession = session; + mArgs = args; + } + + @Override + protected void onStartLoading() { + super.onStartLoading(); + forceLoad(); + } + + @Override + public NetworkStats loadInBackground() { + final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE); + final long start = mArgs.getLong(KEY_START); + final long end = mArgs.getLong(KEY_END); + + try { + return mSession.getSummaryForAllUid(template, start, end, false); + } catch (RemoteException e) { + return null; + } + } + + @Override + protected void onStopLoading() { + super.onStopLoading(); + cancelLoad(); + } + + @Override + protected void onReset() { + super.onReset(); + cancelLoad(); + } +} -- cgit v1.1 From 30275c1924b2bd45b05bd9c98f8648ecbc71374f Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 24 Aug 2015 17:35:49 -0700 Subject: Refactor UidDetailProvider and its dependencies to SettingsLib. so that it can be reused by Wear app data usage. Change-Id: Ifd5709647ba031bb38b2293c35def01bcdee1448 --- packages/SettingsLib/res/values/dimens.xml | 4 +- packages/SettingsLib/res/values/strings.xml | 30 ++++ .../src/com/android/settingslib/Utils.java | 84 +++++++++ .../settingslib/drawable/CircleFramedDrawable.java | 136 +++++++++++++++ .../src/com/android/settingslib/net/UidDetail.java | 27 +++ .../android/settingslib/net/UidDetailProvider.java | 194 +++++++++++++++++++++ 6 files changed, 474 insertions(+), 1 deletion(-) create mode 100644 packages/SettingsLib/src/com/android/settingslib/Utils.java create mode 100644 packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java create mode 100644 packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java create mode 100644 packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java (limited to 'packages/SettingsLib') diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml index 1c4b05f..3ad8f21 100644 --- a/packages/SettingsLib/res/values/dimens.xml +++ b/packages/SettingsLib/res/values/dimens.xml @@ -21,4 +21,6 @@ -32dp - \ No newline at end of file + + 40dp + diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index b03f100..9b1f103 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -195,4 +195,34 @@ Wifi signal full. + + Android OS + + Removed apps + + Removed apps and users + + + + USB tethering + + Portable hotspot + + Bluetooth tethering + + Tethering + + Tethering & portable hotspot + + + Work profile + + + Guest + + + Unknown + + + User: %1$s diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java new file mode 100644 index 0000000..621a09c --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -0,0 +1,84 @@ +package com.android.settingslib; + +import android.content.Context; +import android.content.pm.UserInfo; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.os.UserManager; + +import com.android.internal.util.UserIcons; +import com.android.settingslib.drawable.CircleFramedDrawable; + +public final class Utils { + + /** + * Return string resource that best describes combination of tethering + * options available on this device. + */ + public static int getTetheringLabel(ConnectivityManager cm) { + String[] usbRegexs = cm.getTetherableUsbRegexs(); + String[] wifiRegexs = cm.getTetherableWifiRegexs(); + String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs(); + + boolean usbAvailable = usbRegexs.length != 0; + boolean wifiAvailable = wifiRegexs.length != 0; + boolean bluetoothAvailable = bluetoothRegexs.length != 0; + + if (wifiAvailable && usbAvailable && bluetoothAvailable) { + return R.string.tether_settings_title_all; + } else if (wifiAvailable && usbAvailable) { + return R.string.tether_settings_title_all; + } else if (wifiAvailable && bluetoothAvailable) { + return R.string.tether_settings_title_all; + } else if (wifiAvailable) { + return R.string.tether_settings_title_wifi; + } else if (usbAvailable && bluetoothAvailable) { + return R.string.tether_settings_title_usb_bluetooth; + } else if (usbAvailable) { + return R.string.tether_settings_title_usb; + } else { + return R.string.tether_settings_title_bluetooth; + } + } + + /** + * Returns a label for the user, in the form of "User: user name" or "Work profile". + */ + public static String getUserLabel(Context context, UserInfo info) { + String name = info != null ? info.name : null; + if (info.isManagedProfile()) { + // We use predefined values for managed profiles + return context.getString(R.string.managed_user_title); + } else if (info.isGuest()) { + name = context.getString(R.string.user_guest); + } + if (name == null && info != null) { + name = Integer.toString(info.id); + } else if (info == null) { + name = context.getString(R.string.unknown); + } + return context.getResources().getString(R.string.running_process_item_user_label, name); + } + + /** + * Returns a circular icon for a user. + */ + public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) { + if (user.isManagedProfile()) { + // We use predefined values for managed profiles + Bitmap b = BitmapFactory.decodeResource(context.getResources(), + com.android.internal.R.drawable.ic_corp_icon); + return CircleFramedDrawable.getInstance(context, b); + } + if (user.iconPath != null) { + Bitmap icon = um.getUserIcon(user.id); + if (icon != null) { + return CircleFramedDrawable.getInstance(context, icon); + } + } + return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap( + UserIcons.getDefaultUserIcon(user.id, /* light= */ false))); + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java new file mode 100644 index 0000000..278b57d --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.drawable; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +import com.android.settingslib.R; + +/** + * Converts the user avatar icon to a circularly clipped one. + * TODO: Move this to an internal framework class and share with the one in Keyguard. + */ +public class CircleFramedDrawable extends Drawable { + + private final Bitmap mBitmap; + private final int mSize; + private final Paint mPaint; + + private float mScale; + private Rect mSrcRect; + private RectF mDstRect; + + public static CircleFramedDrawable getInstance(Context context, Bitmap icon) { + Resources res = context.getResources(); + float iconSize = res.getDimension(R.dimen.circle_avatar_size); + + CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize); + return instance; + } + + public CircleFramedDrawable(Bitmap icon, int size) { + super(); + mSize = size; + + mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(mBitmap); + + final int width = icon.getWidth(); + final int height = icon.getHeight(); + final int square = Math.min(width, height); + + final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square); + final RectF circleRect = new RectF(0f, 0f, mSize, mSize); + + final Path fillPath = new Path(); + fillPath.addArc(circleRect, 0f, 360f); + + canvas.drawColor(0, PorterDuff.Mode.CLEAR); + + // opaque circle matte + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setColor(Color.BLACK); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawPath(fillPath, mPaint); + + // mask in the icon where the bitmap is opaque + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(icon, cropRect, circleRect, mPaint); + + // prepare paint for frame drawing + mPaint.setXfermode(null); + + mScale = 1f; + + mSrcRect = new Rect(0, 0, mSize, mSize); + mDstRect = new RectF(0, 0, mSize, mSize); + } + + @Override + public void draw(Canvas canvas) { + final float inside = mScale * mSize; + final float pad = (mSize - inside) / 2f; + + mDstRect.set(pad, pad, mSize - pad, mSize - pad); + canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null); + } + + public void setScale(float scale) { + mScale = scale; + } + + public float getScale() { + return mScale; + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public void setAlpha(int alpha) { + } + + @Override + public void setColorFilter(ColorFilter cf) { + } + + @Override + public int getIntrinsicWidth() { + return mSize; + } + + @Override + public int getIntrinsicHeight() { + return mSize; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java new file mode 100644 index 0000000..5e42281 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.net; + +import android.graphics.drawable.Drawable; + +public class UidDetail { + public CharSequence label; + public CharSequence contentDescription; + public CharSequence[] detailLabels; + public CharSequence[] detailContentDescriptions; + public Drawable icon; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java new file mode 100644 index 0000000..224b967 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.net; + +import android.app.AppGlobals; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.UserInfo; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.net.ConnectivityManager; +import android.net.TrafficStats; +import android.os.UserManager; +import android.os.UserHandle; +import android.os.RemoteException; +import android.text.TextUtils; +import android.util.Log; +import android.util.SparseArray; + +import com.android.settingslib.R; +import com.android.settingslib.Utils; + +/** + * Return details about a specific UID, handling special cases like + * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}. + */ +public class UidDetailProvider { + private static final String TAG = "DataUsage"; + private final Context mContext; + private final SparseArray mUidDetailCache; + + public static final int OTHER_USER_RANGE_START = -2000; + + public static int buildKeyForUser(int userHandle) { + return OTHER_USER_RANGE_START - userHandle; + } + + public static boolean isKeyForUser(int key) { + return key <= OTHER_USER_RANGE_START; + } + + public static int getUserIdForKey(int key) { + return OTHER_USER_RANGE_START - key; + } + + public UidDetailProvider(Context context) { + mContext = context.getApplicationContext(); + mUidDetailCache = new SparseArray(); + } + + public void clearCache() { + synchronized (mUidDetailCache) { + mUidDetailCache.clear(); + } + } + + /** + * Resolve best descriptive label for the given UID. + */ + public UidDetail getUidDetail(int uid, boolean blocking) { + UidDetail detail; + + synchronized (mUidDetailCache) { + detail = mUidDetailCache.get(uid); + } + + if (detail != null) { + return detail; + } else if (!blocking) { + return null; + } + + detail = buildUidDetail(uid); + + synchronized (mUidDetailCache) { + mUidDetailCache.put(uid, detail); + } + + return detail; + } + + /** + * Build {@link UidDetail} object, blocking until all {@link Drawable} + * lookup is finished. + */ + private UidDetail buildUidDetail(int uid) { + final Resources res = mContext.getResources(); + final PackageManager pm = mContext.getPackageManager(); + + final UidDetail detail = new UidDetail(); + detail.label = pm.getNameForUid(uid); + detail.icon = pm.getDefaultActivityIcon(); + + // handle special case labels + switch (uid) { + case android.os.Process.SYSTEM_UID: + detail.label = res.getString(R.string.process_kernel_label); + detail.icon = pm.getDefaultActivityIcon(); + return detail; + case TrafficStats.UID_REMOVED: + detail.label = res.getString(UserManager.supportsMultipleUsers() + ? R.string.data_usage_uninstalled_apps_users + : R.string.data_usage_uninstalled_apps); + detail.icon = pm.getDefaultActivityIcon(); + return detail; + case TrafficStats.UID_TETHERING: + final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + detail.label = res.getString(Utils.getTetheringLabel(cm)); + detail.icon = pm.getDefaultActivityIcon(); + return detail; + } + + final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + + // Handle keys that are actually user handles + if (isKeyForUser(uid)) { + final int userHandle = getUserIdForKey(uid); + final UserInfo info = um.getUserInfo(userHandle); + if (info != null) { + detail.label = Utils.getUserLabel(mContext, info); + detail.icon = Utils.getUserIcon(mContext, um, info); + return detail; + } + } + + // otherwise fall back to using packagemanager labels + final String[] packageNames = pm.getPackagesForUid(uid); + final int length = packageNames != null ? packageNames.length : 0; + try { + final int userId = UserHandle.getUserId(uid); + UserHandle userHandle = new UserHandle(userId); + IPackageManager ipm = AppGlobals.getPackageManager(); + if (length == 1) { + final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0], + 0 /* no flags */, userId); + if (info != null) { + detail.label = info.loadLabel(pm).toString(); + detail.icon = um.getBadgedIconForUser(info.loadIcon(pm), + new UserHandle(userId)); + } + } else if (length > 1) { + detail.detailLabels = new CharSequence[length]; + detail.detailContentDescriptions = new CharSequence[length]; + for (int i = 0; i < length; i++) { + final String packageName = packageNames[i]; + final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); + final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName, + 0 /* no flags */, userId); + + if (appInfo != null) { + detail.detailLabels[i] = appInfo.loadLabel(pm).toString(); + detail.detailContentDescriptions[i] = um.getBadgedLabelForUser( + detail.detailLabels[i], userHandle); + if (packageInfo.sharedUserLabel != 0) { + detail.label = pm.getText(packageName, packageInfo.sharedUserLabel, + packageInfo.applicationInfo).toString(); + detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle); + } + } + } + } + detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle); + } catch (NameNotFoundException e) { + Log.w(TAG, "Error while building UI detail for uid "+uid, e); + } catch (RemoteException e) { + Log.w(TAG, "Error while building UI detail for uid "+uid, e); + } + + if (TextUtils.isEmpty(detail.label)) { + detail.label = Integer.toString(uid); + } + + return detail; + } +} -- cgit v1.1 From 07533dbffff5551ad4c58852b5856f57d7da6801 Mon Sep 17 00:00:00 2001 From: Sanket Padawe Date: Wed, 11 Nov 2015 15:01:35 -0800 Subject: Don't allow contact sharing by default for device not recognized as carkit. + Don't allow contact sharing by default for devices not recognized as carkit at pair time. Bug: 23607427 Change-Id: If6babb10117ba7ee5008a4a29450a7cb981bea4a --- .../com/android/settingslib/bluetooth/CachedBluetoothDevice.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'packages/SettingsLib') diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index e4b1ed8..d994841 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -808,7 +808,12 @@ public final class CachedBluetoothDevice implements Comparable