Merge "Import translations. DO NOT MERGE" into pi-dev
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 9ac54b9..1ef11b1 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1409,6 +1409,7 @@
Landroid/os/Debug$MemoryInfo;->otherSwappedOut:I
Landroid/os/Debug$MemoryInfo;->otherSwappedOutPss:I
Landroid/os/Environment;->buildExternalStorageAppDataDirs(Ljava/lang/String;)[Ljava/io/File;
+Landroid/os/Environment;->getStorageDirectory()Ljava/io/File;
Landroid/os/Environment;->getVendorDirectory()Ljava/io/File;
Landroid/os/Environment;->maybeTranslateEmulatedPathToInternal(Ljava/io/File;)Ljava/io/File;
Landroid/os/FileObserver$ObserverThread;->onEvent(IILjava/lang/String;)V
@@ -1428,6 +1429,19 @@
Landroid/os/Handler;-><init>(Z)V
Landroid/os/Handler;->mCallback:Landroid/os/Handler$Callback;
Landroid/os/Handler;->mMessenger:Landroid/os/IMessenger;
+Landroid/os/health/HealthKeys$Constants;-><init>(Ljava/lang/Class;)V
+Landroid/os/health/HealthStats;-><init>(Landroid/os/Parcel;)V
+Landroid/os/health/HealthStatsParceler;->getHealthStats()Landroid/os/health/HealthStats;
+Landroid/os/health/HealthStatsParceler;-><init>(Landroid/os/health/HealthStatsWriter;)V
+Landroid/os/health/HealthStatsParceler;-><init>(Landroid/os/Parcel;)V
+Landroid/os/health/HealthStatsWriter;->addMeasurement(IJ)V
+Landroid/os/health/HealthStatsWriter;->addMeasurements(ILjava/lang/String;J)V
+Landroid/os/health/HealthStatsWriter;->addStats(ILjava/lang/String;Landroid/os/health/HealthStatsWriter;)V
+Landroid/os/health/HealthStatsWriter;->addTimer(IIJ)V
+Landroid/os/health/HealthStatsWriter;->addTimers(ILjava/lang/String;Landroid/os/health/TimerStat;)V
+Landroid/os/health/HealthStatsWriter;->flattenToParcel(Landroid/os/Parcel;)V
+Landroid/os/health/HealthStatsWriter;-><init>(Landroid/os/health/HealthKeys$Constants;)V
+Landroid/os/health/SystemHealthManager;->from(Landroid/content/Context;)Landroid/os/health/SystemHealthManager;
Landroid/os/HwParcel;-><init>(Z)V
Landroid/os/HwRemoteBinder;-><init>()V
Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1440,6 +1454,7 @@
Landroid/os/IServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
Landroid/os/IServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
Landroid/os/IUserManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/os/LocaleList;->setDefault(Landroid/os/LocaleList;I)V
Landroid/os/Looper;->mQueue:Landroid/os/MessageQueue;
Landroid/os/Looper;->setTraceTag(J)V
Landroid/os/Looper;->sThreadLocal:Ljava/lang/ThreadLocal;
@@ -1455,9 +1470,12 @@
Landroid/os/MessageQueue;->mQuitAllowed:Z
Landroid/os/MessageQueue;->nativePollOnce(JI)V
Landroid/os/MessageQueue;->next()Landroid/os/Message;
+Landroid/os/MessageQueue;->postSyncBarrier()I
+Landroid/os/MessageQueue;->removeSyncBarrier(I)V
Landroid/os/Message;->recycleUnchecked()V
Landroid/os/Message;->target:Landroid/os/Handler;
Landroid/os/Message;->when:J
+Landroid/os/ParcelFileDescriptor;->fromData([BLjava/lang/String;)Landroid/os/ParcelFileDescriptor;
Landroid/os/ParcelFileDescriptor;-><init>(Ljava/io/FileDescriptor;)V
Landroid/os/Parcel;->mNativePtr:J
Landroid/os/Parcel;->readArrayMap(Landroid/util/ArrayMap;Ljava/lang/ClassLoader;)V
@@ -1470,6 +1488,7 @@
Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
+Landroid/os/PowerManager;->nap(J)V
Landroid/os/PowerManager;->userActivity(JZ)V
Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V
@@ -1500,6 +1519,7 @@
Landroid/os/storage/StorageManager;->findVolumeByUuid(Ljava/lang/String;)Landroid/os/storage/VolumeInfo;
Landroid/os/storage/StorageManager;->getBestVolumeDescription(Landroid/os/storage/VolumeInfo;)Ljava/lang/String;
Landroid/os/storage/StorageManager;->getDisks()Ljava/util/List;
+Landroid/os/storage/StorageManager;->getPrimaryVolume()Landroid/os/storage/StorageVolume;
Landroid/os/storage/StorageManager;->getStorageBytesUntilLow(Ljava/io/File;)J
Landroid/os/storage/StorageManager;->getStorageFullBytes(Ljava/io/File;)J
Landroid/os/storage/StorageManager;->getStorageLowBytes(Ljava/io/File;)J
@@ -1520,6 +1540,7 @@
Landroid/os/storage/VolumeInfo;->getType()I
Landroid/os/storage/VolumeInfo;->isPrimary()Z
Landroid/os/storage/VolumeInfo;->isVisible()Z
+Landroid/os/StrictMode;->conditionallyCheckInstanceCounts()V
Landroid/os/StrictMode;->disableDeathOnFileUriExposure()V
Landroid/os/StrictMode;->enterCriticalSpan(Ljava/lang/String;)Landroid/os/StrictMode$Span;
Landroid/os/StrictMode;->getThreadPolicyMask()I
@@ -2117,6 +2138,7 @@
Landroid/util/ArrayMap;->append(Ljava/lang/Object;Ljava/lang/Object;)V
Landroid/util/ArrayMap;->mBaseCacheSize:I
Landroid/util/ArrayMap;->mTwiceBaseCacheSize:I
+Landroid/util/ArraySet;-><init>(Ljava/util/Collection;)V
Landroid/util/DisplayMetrics;->noncompatHeightPixels:I
Landroid/util/DisplayMetrics;->noncompatWidthPixels:I
Landroid/util/EventLog$Event;-><init>([B)V
@@ -3281,6 +3303,7 @@
Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String;
Ldalvik/system/VMRuntime;->getInstructionSet(Ljava/lang/String;)Ljava/lang/String;
Ldalvik/system/VMRuntime;->getRuntime()Ldalvik/system/VMRuntime;
+Ldalvik/system/VMRuntime;->is64BitAbi(Ljava/lang/String;)Z
Ldalvik/system/VMRuntime;->is64Bit()Z
Ldalvik/system/VMRuntime;->newNonMovableArray(Ljava/lang/Class;I)Ljava/lang/Object;
Ldalvik/system/VMRuntime;->registerNativeAllocation(I)V
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 7d8e394..9e4e97a 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -37,6 +37,7 @@
import android.os.Process;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
+import android.util.ArraySet;
import android.util.Log;
import java.util.ArrayList;
@@ -513,7 +514,7 @@
.detectAll()
.penaltyDeath()
.build());
- return onBindSlice(sliceUri, supportedSpecs);
+ return onBindSlice(sliceUri, new ArraySet<>(supportedSpecs));
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index a9d0911..0c5f228 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -302,6 +302,12 @@
public abstract boolean isPackageDataProtected(int userId, String packageName);
/**
+ * Returns {@code true} if a given package's state is protected, e.g. it cannot be force
+ * stopped, suspended, disabled or hidden. Otherwise, returns {@code false}.
+ */
+ public abstract boolean isPackageStateProtected(String packageName, int userId);
+
+ /**
* Returns {@code true} if a given package is installed as ephemeral. Otherwise, returns
* {@code false}.
*/
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 2a878eb..435bcb0 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -411,7 +411,8 @@
/**
* Checks, if a given AM/FM frequency is roughly valid and in correct unit.
*
- * It does not check the range precisely. In particular, it may be way off for certain regions.
+ * It does not check the range precisely: it may provide false positives, but not false
+ * negatives. In particular, it may be way off for certain regions.
* The main purpose is to avoid passing inproper units, ie. MHz instead of kHz.
*
* @param isAm true, if AM, false if FM.
@@ -420,7 +421,7 @@
*/
private static boolean isValidAmFmFrequency(boolean isAm, int frequencyKhz) {
if (isAm) {
- return frequencyKhz > 150 && frequencyKhz < 30000;
+ return frequencyKhz > 150 && frequencyKhz <= 30000;
} else {
return frequencyKhz > 60000 && frequencyKhz < 110000;
}
@@ -462,7 +463,8 @@
throw new IllegalArgumentException("Subchannels are not supported for non-HD radio");
}
if (!isValidAmFmFrequency(isAm, frequencyKhz)) {
- throw new IllegalArgumentException("Provided value is not a valid AM/FM frequency");
+ throw new IllegalArgumentException("Provided value is not a valid AM/FM frequency: "
+ + frequencyKhz);
}
// We can't use AM_HD or FM_HD, because we don't know HD station ID.
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a8e8179..65dfb13 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -71,6 +71,7 @@
mUids = nc.mUids;
mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
+ mSSID = nc.mSSID;
}
}
@@ -86,6 +87,7 @@
mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
mUids = null;
mEstablishingVpnAppUid = INVALID_UID;
+ mSSID = null;
}
/**
@@ -921,7 +923,7 @@
/**
* Sets the signal strength. This is a signed integer, with higher values indicating a stronger
* signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units
- * reported by WifiManager.
+ * reported by wifi code.
* <p>
* Note that when used to register a network callback, this specifies the minimum acceptable
* signal strength. When received as the state of an existing network it specifies the current
@@ -1053,7 +1055,7 @@
}
/**
- * Tests if the set of UIDs that this network applies to is the same of the passed set of UIDs.
+ * Tests if the set of UIDs that this network applies to is the same as the passed network.
* <p>
* This test only checks whether equal range objects are in both sets. It will
* return false if the ranges are not exactly the same, even if the covered UIDs
@@ -1143,6 +1145,62 @@
mUids.addAll(nc.mUids);
}
+
+ /**
+ * The SSID of the network, or null if not applicable or unknown.
+ * <p>
+ * This is filled in by wifi code.
+ * @hide
+ */
+ private String mSSID;
+
+ /**
+ * Sets the SSID of this network.
+ * @hide
+ */
+ public NetworkCapabilities setSSID(String ssid) {
+ mSSID = ssid;
+ return this;
+ }
+
+ /**
+ * Gets the SSID of this network, or null if none or unknown.
+ * @hide
+ */
+ public String getSSID() {
+ return mSSID;
+ }
+
+ /**
+ * Tests if the SSID of this network is the same as the SSID of the passed network.
+ * @hide
+ */
+ public boolean equalsSSID(NetworkCapabilities nc) {
+ return Objects.equals(mSSID, nc.mSSID);
+ }
+
+ /**
+ * Check if the SSID requirements of this object are matched by the passed object.
+ * @hide
+ */
+ public boolean satisfiedBySSID(NetworkCapabilities nc) {
+ return mSSID == null || mSSID.equals(nc.mSSID);
+ }
+
+ /**
+ * Combine SSIDs of the capabilities.
+ * <p>
+ * This is only legal if either the SSID of this object is null, or both SSIDs are
+ * equal.
+ * @hide
+ */
+ private void combineSSIDs(NetworkCapabilities nc) {
+ if (mSSID != null && !mSSID.equals(nc.mSSID)) {
+ throw new IllegalStateException("Can't combine two SSIDs");
+ }
+ setSSID(nc.mSSID);
+ }
+
/**
* Combine a set of Capabilities to this one. Useful for coming up with the complete set
* @hide
@@ -1154,6 +1212,7 @@
combineSpecifiers(nc);
combineSignalStrength(nc);
combineUids(nc);
+ combineSSIDs(nc);
}
/**
@@ -1172,7 +1231,8 @@
&& (onlyImmutable || satisfiedByLinkBandwidths(nc))
&& satisfiedBySpecifier(nc)
&& (onlyImmutable || satisfiedBySignalStrength(nc))
- && (onlyImmutable || satisfiedByUids(nc)));
+ && (onlyImmutable || satisfiedByUids(nc))
+ && (onlyImmutable || satisfiedBySSID(nc)));
}
/**
@@ -1259,7 +1319,8 @@
&& equalsLinkBandwidths(that)
&& equalsSignalStrength(that)
&& equalsSpecifier(that)
- && equalsUids(that));
+ && equalsUids(that)
+ && equalsSSID(that));
}
@Override
@@ -1274,7 +1335,8 @@
+ (mLinkDownBandwidthKbps * 19)
+ Objects.hashCode(mNetworkSpecifier) * 23
+ (mSignalStrength * 29)
- + Objects.hashCode(mUids) * 31;
+ + Objects.hashCode(mUids) * 31
+ + Objects.hashCode(mSSID) * 37;
}
@Override
@@ -1291,6 +1353,7 @@
dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
dest.writeInt(mSignalStrength);
dest.writeArraySet(mUids);
+ dest.writeString(mSSID);
}
public static final Creator<NetworkCapabilities> CREATOR =
@@ -1308,6 +1371,7 @@
netCap.mSignalStrength = in.readInt();
netCap.mUids = (ArraySet<UidRange>) in.readArraySet(
null /* ClassLoader, null for default */);
+ netCap.mSSID = in.readString();
return netCap;
}
@Override
@@ -1358,6 +1422,10 @@
sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid);
}
+ if (null != mSSID) {
+ sb.append(" SSID: ").append(mSSID);
+ }
+
sb.append("]");
return sb.toString();
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 7b01f7a..e3f4ad1 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1470,6 +1470,17 @@
}
/**
+ * Determines if DND is currently overriding the ringer
+ */
+ public static boolean isZenOverridingRinger(int zen, ZenModeConfig zenConfig) {
+ // TODO (beverlyt): check if apps can bypass dnd b/77729075
+ return zen == Global.ZEN_MODE_NO_INTERRUPTIONS
+ || zen == Global.ZEN_MODE_ALARMS
+ || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(zenConfig));
+ }
+
+ /**
* Determines whether dnd behavior should mute all sounds controlled by ringer
*/
public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(ZenModeConfig config) {
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 0482f6c..5729b53 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -107,21 +107,23 @@
}
}
}
- if (notGoneChildren > 1 && needRebuild) {
+ boolean centerAligned = (mGravity & Gravity.CENTER_HORIZONTAL) != 0;
+ boolean singleChildCentered = notGoneChildren == 1 && centerAligned;
+ boolean needsRegularMeasurement = notGoneChildren > 1 || singleChildCentered;
+
+ if (needsRegularMeasurement && needRebuild) {
rebuildMeasureOrder(textViews, otherViews);
}
final boolean constrained =
MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED;
- final boolean centerAligned = (mGravity & Gravity.CENTER_HORIZONTAL) != 0;
final int innerWidth = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
final int otherSize = mMeasureOrderOther.size();
int usedWidth = 0;
- // Optimization: Don't do this if there's only one child.
int measuredChildren = 0;
- for (int i = 0; i < N && notGoneChildren > 1; i++) {
+ for (int i = 0; i < N && needsRegularMeasurement; i++) {
// Measure shortest children first. To avoid measuring twice, we approximate by looking
// at the text length.
View c;
diff --git a/core/res/res/layout/car_user_switching_dialog.xml b/core/res/res/layout/car_user_switching_dialog.xml
new file mode 100644
index 0000000..7ce35df
--- /dev/null
+++ b/core/res/res/layout/car_user_switching_dialog.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fitsSystemWindows="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <ImageView
+ android:id="@+id/user_loading_avatar"
+ android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
+ android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+ android:layout_centerHorizontal="true"
+ />
+
+ <TextView android:id="@+id/user_loading"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/car_padding_4"
+ android:textSize="@dimen/car_body1_size"
+ android:textColor="@color/car_body1_light"
+ android:layout_below="@id/user_loading_avatar"
+ android:gravity="center"
+ />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/user_switching_dialog.xml b/core/res/res/layout/user_switching_dialog.xml
index 496783a..c806210 100644
--- a/core/res/res/layout/user_switching_dialog.xml
+++ b/core/res/res/layout/user_switching_dialog.xml
@@ -24,4 +24,4 @@
android:paddingStart="?attr/dialogPreferredPadding"
android:paddingEnd="?attr/dialogPreferredPadding"
android:paddingTop="24dp"
- android:paddingBottom="24dp" />
+ android:paddingBottom="24dp" />
\ No newline at end of file
diff --git a/core/res/res/values/colors_car.xml b/core/res/res/values/colors_car.xml
new file mode 100644
index 0000000..6053728
--- /dev/null
+++ b/core/res/res/values/colors_car.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2018, 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.
+ */
+-->
+<resources>
+ <!-- car support colors from
+ https://cs.corp.google.com/android/frameworks/support/car/res/values/colors.xml -->
+ <color name="car_user_switcher_user_image_bgcolor">@color/car_grey_50</color>
+ <color name="car_user_switcher_user_image_fgcolor">@color/car_grey_900</color>
+ <color name="car_card_dark">@color/car_dark_blue_grey_700</color>
+ <color name="car_body1_light">@color/car_grey_100</color>
+
+ <color name="car_grey_50">#fffafafa</color>
+ <color name="car_grey_900">#ff212121</color>
+ <color name="car_dark_blue_grey_700">#ff172026</color>
+ <color name="car_grey_100">#fff5f5f5</color>
+</resources>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
new file mode 100644
index 0000000..7d14f86
--- /dev/null
+++ b/core/res/res/values/dimens_car.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2018, 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.
+*/
+-->
+<resources>
+ <!-- TODO replace with car support lib sizes when available -->
+ <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
+ <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
+ <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
+ <dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
+ <dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
+ <dimen name="car_padding_4">20dp</dimen>
+ <dimen name="car_body1_size">32sp</dimen>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 04f4d6e..3571967 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4957,4 +4957,8 @@
<string name="notification_app_name_system">System</string>
<!-- Application name displayed in notifications [CHAR LIMIT=60] -->
<string name="notification_app_name_settings">Settings</string>
+
+ <!-- Strings for car -->
+ <!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
+ <string name="car_loading_profile">Loading</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 129a952..0de2cb0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3344,4 +3344,19 @@
<java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
+ <!-- For car devices -->
+ <java-symbol type="string" name="car_loading_profile" />
+ <java-symbol type="color" name="car_body1_light" />
+ <java-symbol type="color" name="car_user_switcher_user_image_bgcolor" />
+ <java-symbol type="color" name="car_user_switcher_user_image_fgcolor" />
+ <java-symbol type="color" name="car_card_dark" />
+ <java-symbol type="dimen" name="car_body1_size" />
+ <java-symbol type="dimen" name="car_padding_4" />
+ <java-symbol type="dimen" name="car_fullscreen_user_pod_icon_text_size" />
+ <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_height" />
+ <java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_width" />
+ <java-symbol type="layout" name="car_user_switching_dialog" />
+ <java-symbol type="id" name="user_loading_avatar" />
+ <java-symbol type="id" name="user_loading" />
+
</resources>
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index efee8b4..1be8309 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -156,7 +156,7 @@
break;
}
case ID_TYPE_MEID: {
- final String meid = telephonyService.getDeviceId();
+ final String meid = telephonyService.getMeid(0);
if (meid == null) {
throw new DeviceIdAttestationException("Unable to retrieve MEID");
}
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 69fbb99..91bc505c 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -22,6 +22,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.NETWORK_STACK" />
<application android:label="@string/app_name"
android:usesCleartextTraffic="true">
diff --git a/packages/CaptivePortalLogin/res/values-in/strings.xml b/packages/CaptivePortalLogin/res/values-in/strings.xml
index f9f6481..10e3de6 100644
--- a/packages/CaptivePortalLogin/res/values-in/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-in/strings.xml
@@ -4,7 +4,7 @@
<string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
<string name="action_use_network" msgid="6076184727448466030">"Gunakan jaringan ini sebagaimana adanya"</string>
<string name="action_do_not_use_network" msgid="4577366536956516683">"Jangan gunakan jaringan ini"</string>
- <string name="action_bar_label" msgid="917235635415966620">"Masuk ke jaringan"</string>
+ <string name="action_bar_label" msgid="917235635415966620">"Login ke jaringan"</string>
<string name="action_bar_title" msgid="5645564790486983117">"Login ke %1$s"</string>
<string name="ssl_error_warning" msgid="6653188881418638872">"Jaringan yang ingin Anda masuki mengalami masalah keamanan."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Misalnya, halaman masuk mungkin bukan milik organisasi yang ditampilkan."</string>
diff --git a/packages/CaptivePortalLogin/res/values-mr/strings.xml b/packages/CaptivePortalLogin/res/values-mr/strings.xml
index fac0a08..6ea9006 100644
--- a/packages/CaptivePortalLogin/res/values-mr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-mr/strings.xml
@@ -6,7 +6,7 @@
<string name="action_do_not_use_network" msgid="4577366536956516683">"हे नेटवर्क वापरू नका"</string>
<string name="action_bar_label" msgid="917235635415966620">"नेटवर्क मध्ये साइन इन करा"</string>
<string name="action_bar_title" msgid="5645564790486983117">"%1$sमध्ये साइन इन करा"</string>
- <string name="ssl_error_warning" msgid="6653188881418638872">"ज्या नेटवर्कमध्ये आपण सामील होण्याचा प्रयत्न करीत आहात त्यात सुरक्षितता समस्या आहेत."</string>
+ <string name="ssl_error_warning" msgid="6653188881418638872">"ज्या नेटवर्कमध्ये तुम्ही सामील होण्याचा प्रयत्न करीत आहात त्यात सुरक्षितता समस्या आहेत."</string>
<string name="ssl_error_example" msgid="647898534624078900">"उदाहरणार्थ, लॉगिन पृष्ठ कदाचित दर्शविलेल्या संस्थेच्या मालकीचे नसावे."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउझरद्वारे तरीही सुरु ठेवा"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index cdc3867..0e2a0e0 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -26,12 +26,12 @@
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.Proxy;
import android.net.Uri;
import android.net.dns.ResolvUtil;
import android.net.http.SslError;
+import android.net.wifi.WifiInfo;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
@@ -534,15 +534,12 @@
}
private String getHeaderTitle() {
- NetworkInfo info = mCm.getNetworkInfo(mNetwork);
- if (info == null || TextUtils.isEmpty(info.getExtraInfo())) {
- return getString(R.string.action_bar_label);
- }
NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
- if (!nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ if (nc == null || TextUtils.isEmpty(nc.getSSID())
+ || !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return getString(R.string.action_bar_label);
}
- return getString(R.string.action_bar_title, info.getExtraInfo().replaceAll("^\"|\"$", ""));
+ return getString(R.string.action_bar_title, WifiInfo.removeDoubleQuotes(nc.getSSID()));
}
private String getHeaderSubtitle(URL url) {
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index 7e7792f..e1442c2 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -11,7 +11,7 @@
<string name="no_mobile_data_connection" msgid="544980465184147010">"%sने डेटा किंवा रोमिंग प्लॅन जोडा"</string>
<string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"मोबाइल डेटा स्थिती"</string>
<string name="action_bar_label" msgid="4290345990334377177">"मोबाइल नेटवर्कमध्ये साइन इन करा"</string>
- <string name="ssl_error_warning" msgid="3127935140338254180">"आपण ज्या नेटवर्कमध्ये सामील होण्याचा प्रयत्न करत आहात त्यात सुरक्षितता समस्या आहेत."</string>
+ <string name="ssl_error_warning" msgid="3127935140338254180">"तुम्ही ज्या नेटवर्कमध्ये सामील होण्याचा प्रयत्न करत आहात त्यात सुरक्षितता समस्या आहेत."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index 39d00d4..4bb1611 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -3,7 +3,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="8016145283189546017">"Beviteli eszközök"</string>
<string name="keyboard_layouts_label" msgid="6688773268302087545">"Android-billentyűzet"</string>
- <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"angol (Egyesült Királyság)"</string>
+ <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"angol (brit)"</string>
<string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"angol (USA)"</string>
<string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"angol (USA), nemzetközi stílus"</string>
<string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"angol (USA), Colemak-stílus"</string>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 207f5f9..49bf0b7 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -35,13 +35,13 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенский"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецкий"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украинский"</string>
- <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабский"</string>
- <string name="keyboard_layout_greek" msgid="7289253560162386040">"Греческий"</string>
- <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Иврит"</string>
- <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовский"</string>
- <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испанский (Латинская Америка)"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"арабский"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"греческий"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"иврит"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"литовский"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"испанский (Латинская Америка)"</string>
<string name="keyboard_layout_latvian" msgid="4405417142306250595">"латышский"</string>
<string name="keyboard_layout_persian" msgid="3920643161015888527">"Персидский"</string>
<string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Азербайджанский"</string>
- <string name="keyboard_layout_polish" msgid="1121588624094925325">"Польский"</string>
+ <string name="keyboard_layout_polish" msgid="1121588624094925325">"польский"</string>
</resources>
diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml
index 441c2c2..3bd637b 100644
--- a/packages/InputDevices/res/values-uz/strings.xml
+++ b/packages/InputDevices/res/values-uz/strings.xml
@@ -3,20 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="8016145283189546017">"Kiritish qurilmalari"</string>
<string name="keyboard_layouts_label" msgid="6688773268302087545">"Android klaviaturasi"</string>
- <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Inglizcha (BQ)"</string>
- <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Inglizcha (AQSH)"</string>
- <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglizcha (AQSH), xalqaro uslubda"</string>
- <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglizcha (AQSH), Kolemak uslubida"</string>
- <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglizcha (AQSH), Dvorak uslubida"</string>
+ <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"Ingliz (Birlashgan Qirollik)"</string>
+ <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"Ingliz (AQSH)"</string>
+ <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Ingliz (AQSH), xalqaro"</string>
+ <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Ingliz (AQSH), Kolemak"</string>
+ <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Ingliz (AQSH), Dvorak"</string>
<string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Ingliz (AQSH), ishchi uslubda"</string>
- <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Nemischa"</string>
+ <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Nemis"</string>
<string name="keyboard_layout_french_label" msgid="813450119589383723">"Fransuzcha"</string>
<string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Fransuzcha (Kanada)"</string>
<string name="keyboard_layout_russian_label" msgid="8724879775815042968">"Ruscha"</string>
<string name="keyboard_layout_russian_mac_label" msgid="3795866869038264796">"Ruscha, Mac uslubida"</string>
<string name="keyboard_layout_spanish_label" msgid="7091555148131908240">"Ispancha"</string>
<string name="keyboard_layout_swiss_french_label" msgid="4659191025396371684">"Shveytsar fransuzcha"</string>
- <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Shveytsar nemischa"</string>
+ <string name="keyboard_layout_swiss_german_label" msgid="2305520941993314258">"Nemis (Shveytsariya)"</string>
<string name="keyboard_layout_belgian" msgid="2011984572838651558">"Belgiyancha"</string>
<string name="keyboard_layout_bulgarian" msgid="8951224309972028398">"Bolgarcha"</string>
<string name="keyboard_layout_italian" msgid="6497079660449781213">"Italyancha"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 6413aab..1e0cce9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -34,6 +34,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.ParcelUuid;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.internal.R;
import java.util.ArrayList;
@@ -41,6 +42,7 @@
import java.util.HashMap;
import java.util.Map;
+
/**
* LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
* objects for the available Bluetooth profiles.
@@ -130,7 +132,7 @@
addProfile(mHidProfile, HidProfile.NAME,
BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
- mPanProfile = new PanProfile(context);
+ mPanProfile = new PanProfile(context, mLocalAdapter);
addPanProfile(mPanProfile, PanProfile.NAME,
BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
@@ -486,6 +488,16 @@
return mHearingAidProfile;
}
+ @VisibleForTesting
+ HidProfile getHidProfile() {
+ return mHidProfile;
+ }
+
+ @VisibleForTesting
+ HidDeviceProfile getHidDeviceProfile() {
+ return mHidDeviceProfile;
+ }
+
/**
* Fill in a list of LocalBluetoothProfile objects that are supported by
* the local device and the remote device.
@@ -553,7 +565,7 @@
removedProfiles.remove(mHidProfile);
}
- if (mHidProfile != null && mHidDeviceProfile.getConnectionStatus(device)
+ if (mHidDeviceProfile != null && mHidDeviceProfile.getConnectionStatus(device)
!= BluetoothProfile.STATE_DISCONNECTED) {
profiles.add(mHidDeviceProfile);
removedProfiles.remove(mHidDeviceProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
index 3299cb2..e077a67 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
@@ -38,6 +38,7 @@
private BluetoothPan mService;
private boolean mIsProfileReady;
+ private final LocalBluetoothAdapter mLocalAdapter;
// Tethering direction for each device
private final HashMap<BluetoothDevice, Integer> mDeviceRoleMap =
@@ -68,10 +69,10 @@
return mIsProfileReady;
}
- PanProfile(Context context) {
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- adapter.getProfileProxy(context, new PanServiceListener(),
- BluetoothProfile.PAN);
+ PanProfile(Context context, LocalBluetoothAdapter adapter) {
+ mLocalAdapter = adapter;
+ mLocalAdapter.getProfileProxy(context, new PanServiceListener(),
+ BluetoothProfile.PAN);
}
public boolean isConnectable() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
new file mode 100644
index 0000000..88c7a55
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(resourceDir = "../../res")
+public class LocalBluetoothProfileManagerTest {
+ @Mock private CachedBluetoothDeviceManager mDeviceManager;
+ @Mock private BluetoothEventManager mEventManager;
+ @Mock private LocalBluetoothAdapter mAdapter;
+ @Mock private BluetoothDevice mDevice;
+ private Context mContext;
+ private LocalBluetoothProfileManager mProfileManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+ }
+
+ /**
+ * Verify HID and HID Device profiles are not null without running updateUuids()
+ */
+ @Test
+ public void constructor_initiateHidAndHidDeviceProfile() {
+ mProfileManager =
+ new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+
+ assertThat(mProfileManager.getHidProfile()).isNotNull();
+ assertThat(mProfileManager.getHidDeviceProfile()).isNotNull();
+ }
+
+ /**
+ * Verify updateLocalProfiles() for a local A2DP source adds A2dpProfile
+ */
+ @Test
+ public void updateLocalProfiles_addA2dpToLocalProfiles() {
+ mProfileManager =
+ new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+ when(mAdapter.getUuids()).thenReturn(new ParcelUuid[] {BluetoothUuid.AudioSource});
+ assertThat(mProfileManager.getA2dpProfile()).isNull();
+ assertThat(mProfileManager.getHeadsetProfile()).isNull();
+
+ ParcelUuid[] uuids = mAdapter.getUuids();
+ mProfileManager.updateLocalProfiles(uuids);
+
+ assertThat(mProfileManager.getA2dpProfile()).isNotNull();
+ assertThat(mProfileManager.getHeadsetProfile()).isNull();
+ }
+
+ /**
+ * Verify updateProfiles() for a remote HID device updates profiles and removedProfiles
+ */
+ @Test
+ public void updateProfiles_addHidProfileForRemoteDevice() {
+ mProfileManager =
+ new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, mEventManager);
+ ParcelUuid[] uuids = new ParcelUuid[]{BluetoothUuid.Hid};
+ ParcelUuid[] localUuids = new ParcelUuid[]{};
+ List<LocalBluetoothProfile> profiles = new ArrayList<>();
+ List<LocalBluetoothProfile> removedProfiles = new ArrayList<>();
+
+ mProfileManager.updateProfiles(uuids, localUuids, profiles, removedProfiles, false,
+ mDevice);
+
+ assertThat(mProfileManager.getHidProfile()).isNotNull();
+ assertThat(profiles.contains(mProfileManager.getHidProfile())).isTrue();
+ assertThat(removedProfiles.contains(mProfileManager.getHidProfile())).isFalse();
+ }
+}
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 67f68d3..c59b067 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -37,7 +37,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/car_padding_4"
android:textSize="@dimen/car_body1_size"
- android:textColor="@color/qs_user_detail_name"
+ android:textColor="@color/car_body1_light"
android:ellipsize="end"
android:singleLine="true"
android:gravity="center"
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 22452b7..27d0e46 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -18,20 +18,12 @@
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@android:color/black"
+ android:background="@color/car_card_dark"
android:visibility="gone">
- <!-- This progressbar is activated while we're switching users. -->
- <ProgressBar
- android:id="@+id/switching_users"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:indeterminate="true"
- android:visibility="gone"
- android:layout_gravity="center" />
-
<RelativeLayout
android:id="@+id/container"
+ android:background="@color/car_card_dark"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 2b91891..0cd3825 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -20,7 +20,7 @@
<dimen name="car_margin_standard">112dp</dimen>
<!-- TODO replace with car support lib sizes when available -->
- <dimen name="car_fullscreen_user_pod_icon_text_size">32sp</dimen>
+ <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
<dimen name="car_fullscreen_user_pod_width">243dp</dimen>
<dimen name="car_fullscreen_user_pod_height">356dp</dimen>
<dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 0f52209..2bdbf0b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,8 +16,7 @@
package com.android.systemui.shared.system;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-
+import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.RemoteAnimationTarget;
@@ -29,9 +28,16 @@
public static final int MODE_OPENING = RemoteAnimationTarget.MODE_OPENING;
public static final int MODE_CLOSING = RemoteAnimationTarget.MODE_CLOSING;
+ public final int mode;
+
+ public static final int ACTIVITY_TYPE_UNDEFINED = WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+ public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+ public static final int ACTIVITY_TYPE_HOME = WindowConfiguration.ACTIVITY_TYPE_HOME;
+ public static final int ACTIVITY_TYPE_RECENTS = WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+ public static final int ACTIVITY_TYPE_ASSISTANT = WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+ public final int activityType;
public final int taskId;
- public final int mode;
public final SurfaceControlCompat leash;
public final boolean isTranslucent;
public final Rect clipRect;
@@ -39,11 +45,9 @@
public final Point position;
public final Rect sourceContainerBounds;
public final boolean isNotInRecents;
-
- private final RemoteAnimationTarget mTarget;
+ public final Rect contentInsets;
public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
- mTarget = app;
taskId = app.taskId;
mode = app.mode;
leash = new SurfaceControlCompat(app.leash);
@@ -53,6 +57,8 @@
sourceContainerBounds = app.sourceContainerBounds;
prefixOrderIndex = app.prefixOrderIndex;
isNotInRecents = app.isNotInRecents;
+ contentInsets = app.contentInsets;
+ activityType = app.windowConfiguration.getActivityType();
}
public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
@@ -63,18 +69,4 @@
}
return appsCompat;
}
-
- /**
- * TODO: Get as a method for compatibility (will move into ctor once Launcher updates)
- */
- public Rect getContentInsets() {
- return mTarget.contentInsets;
- }
-
- /**
- * TODO: Get as a method for compatibility (will move into ctor once Launcher updates)
- */
- public boolean isAssistantActivityType() {
- return mTarget.windowConfiguration.getActivityType() == ACTIVITY_TYPE_ASSISTANT;
- }
}
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SettingsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SettingsCompat.java
new file mode 100644
index 0000000..c16cf92
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SettingsCompat.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 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.systemui.shared.system;
+
+import android.provider.Settings;
+
+public class SettingsCompat {
+
+ public static final String SWIPE_UP_SETTING_NAME
+ = Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index 302face..56cb888 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -25,6 +25,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
+import android.text.BidiFormatter;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -50,8 +51,10 @@
try {
PackageManager pm = getPackageManager();
- CharSequence app1 = pm.getApplicationInfo(mCallingPkg, 0).loadLabel(pm);
- CharSequence app2 = pm.getApplicationInfo(mProviderPkg, 0).loadLabel(pm);
+ CharSequence app1 = BidiFormatter.getInstance().unicodeWrap(
+ pm.getApplicationInfo(mCallingPkg, 0).loadSafeLabel(pm).toString());
+ CharSequence app2 = BidiFormatter.getInstance().unicodeWrap(
+ pm.getApplicationInfo(mProviderPkg, 0).loadSafeLabel(pm).toString());
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle(getString(R.string.slice_permission_title, app1, app2))
.setView(R.layout.slice_permission_request)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 70880d3..d1913df 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -32,6 +32,7 @@
import android.media.AudioManager;
import android.os.Handler;
import android.provider.AlarmClock;
+import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
import android.text.format.DateUtils;
import android.util.AttributeSet;
@@ -48,10 +49,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSDetail.Callback;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
@@ -61,8 +60,10 @@
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.ZenModeController;
import java.util.Locale;
+import java.util.Objects;
/**
* View that contains the top-most bits of the screen (primarily the status bar with date, time, and
@@ -70,7 +71,8 @@
* contents.
*/
public class QuickStatusBarHeader extends RelativeLayout implements
- View.OnClickListener, NextAlarmController.NextAlarmChangeCallback {
+ View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
+ ZenModeController.Callback {
private static final String TAG = "QuickStatusBarHeader";
private static final boolean DEBUG = false;
@@ -117,6 +119,7 @@
private DateView mDateView;
private NextAlarmController mAlarmController;
+ private ZenModeController mZenController;
/** Counts how many times the long press tooltip has been shown to the user. */
private int mShownCount;
@@ -136,6 +139,7 @@
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
mAlarmController = Dependency.get(NextAlarmController.class);
+ mZenController = Dependency.get(ZenModeController.class);
mShownCount = getStoredShownCount();
}
@@ -182,19 +186,45 @@
}
private void updateStatusText() {
+ boolean changed = updateRingerStatus() || updateAlarmStatus();
+
+ if (changed) {
+ boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
+ boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
+ mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
+ : View.GONE);
+ updateTooltipShow();
+ }
+ }
+
+ private boolean updateRingerStatus() {
+ boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
+ CharSequence originalRingerText = mRingerModeTextView.getText();
+
boolean ringerVisible = false;
- if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
- mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_vibrate);
- mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
- ringerVisible = true;
- } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
- mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_silent);
- mRingerModeTextView.setText(R.string.qs_status_phone_muted);
- ringerVisible = true;
+ if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
+ mZenController.getConfig())) {
+ if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_vibrate);
+ mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
+ ringerVisible = true;
+ } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
+ mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_silent);
+ mRingerModeTextView.setText(R.string.qs_status_phone_muted);
+ ringerVisible = true;
+ }
}
mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
+ return isOriginalVisible != ringerVisible ||
+ !Objects.equals(originalRingerText, mRingerModeTextView.getText());
+ }
+
+ private boolean updateAlarmStatus() {
+ boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
+ CharSequence originalAlarmText = mNextAlarmTextView.getText();
+
boolean alarmVisible = false;
if (mNextAlarm != null) {
alarmVisible = true;
@@ -202,10 +232,10 @@
}
mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
- mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE : View.GONE);
- updateTooltipShow();
- }
+ return isOriginalVisible != alarmVisible ||
+ !Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
+ }
private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
View v = findViewById(id);
@@ -368,10 +398,12 @@
mListening = listening;
if (listening) {
+ mZenController.addCallback(this);
mAlarmController.addCallback(this);
mContext.registerReceiver(mRingerReceiver,
new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
} else {
+ mZenController.removeCallback(this);
mAlarmController.removeCallback(this);
mContext.unregisterReceiver(mRingerReceiver);
}
@@ -391,6 +423,17 @@
updateStatusText();
}
+ @Override
+ public void onZenChanged(int zen) {
+ updateStatusText();
+
+ }
+
+ @Override
+ public void onConfigChanged(ZenModeConfig config) {
+ updateStatusText();
+ }
+
private void updateTooltipShow() {
if (hasStatusText()) {
hideLongPressTooltip(true /* shouldShowStatusText */);
@@ -547,5 +590,4 @@
public static float getColorIntensity(@ColorInt int color) {
return color == Color.WHITE ? 0 : 1;
}
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 4aa83d0..394c322 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -217,7 +217,7 @@
}
public boolean isCustomizing() {
- return mCustomizing;
+ return mCustomizing || mOpening;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 6104599..c1af1fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.view.View;
import android.view.ViewStub;
-import android.widget.ProgressBar;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
@@ -37,7 +36,6 @@
private final View mContainer;
private final View mParent;
private final UserGridRecyclerView mUserGridView;
- private final ProgressBar mSwitchingUsers;
private final int mShortAnimDuration;
private final StatusBar mStatusBar;
private final UserManagerHelper mUserManagerHelper;
@@ -60,8 +58,6 @@
mShortAnimDuration = mContainer.getResources()
.getInteger(android.R.integer.config_shortAnimTime);
-
- mSwitchingUsers = mParent.findViewById(R.id.switching_users);
}
public void show() {
@@ -112,10 +108,11 @@
private void toggleSwitchInProgress(boolean inProgress) {
if (inProgress) {
- crossFade(mSwitchingUsers, mContainer);
+ crossFade(mParent, mContainer);
} else {
- crossFade(mContainer, mSwitchingUsers);
+ crossFade(mContainer, mParent);
}
+
}
private void crossFade(View incoming, View outgoing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/PageIndicator.java
deleted file mode 100644
index c830ff8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/PageIndicator.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2017 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.systemui.statusbar.car;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-
-import com.android.systemui.R;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Displays the dots underneath the ViewPager on the lock screen. This is really just a simplified
- * version of PagerTitleStrip. We don't inherit from there because it's impossible to bypass some
- * of the overriden logic in that class.
- */
-public class PageIndicator extends View {
- private static final String TAG = "PageIndicator";
- // These can be made a styleable attribute in the future if necessary.
- private static final int SELECTED_COLOR = 0xFFF5F5F5; // grey 100
- private static final int UNSELECTED_COLOR = 0xFFBDBDBD; // grey 400
- private final PageListener mPageListener = new PageListener();
-
- private ViewPager mPager;
- private WeakReference<PagerAdapter> mWatchingAdapter;
-
- private int mPageCount;
- private int mCurrentPosition;
- private Paint mPaint;
- private int mRadius;
- private int mStep;
-
- public PageIndicator(Context context) {
- super(context);
- init();
- }
-
- public PageIndicator(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- private void init() {
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaint.setStyle(Paint.Style.FILL);
- mRadius = getResources().getDimensionPixelSize(R.dimen.car_page_indicator_dot_diameter) / 2;
- mStep = mRadius * 3;
- }
-
- public void setupWithViewPager(ViewPager pager) {
- mPager = pager;
-
- final PagerAdapter adapter = (PagerAdapter) pager.getAdapter();
- pager.addOnPageChangeListener(mPageListener);
- pager.addOnAdapterChangeListener(mPageListener);
- updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
- invalidate();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (mPager != null) {
- updateAdapter(mPager.getAdapter(), null);
- mPager.removeOnPageChangeListener(mPageListener);
- mPager.removeOnAdapterChangeListener(mPageListener);
- mPager = null;
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- // Don't draw anything unless there's multiple pages to scroll through. No need to clear
- // any previous dots, since onDraw provides a canvas that's already cleared.
- if (mPageCount <= 1)
- return;
-
- int x = canvas.getWidth() / 2 - (mPageCount / 2) * mStep;
- int y = canvas.getHeight() / 2;
-
- for (int i = 0; i < mPageCount; i++) {
- if (i == mCurrentPosition) {
- mPaint.setColor(SELECTED_COLOR);
- } else {
- mPaint.setColor(UNSELECTED_COLOR);
- }
-
- canvas.drawCircle(x, y, mRadius, mPaint);
- x += mStep;
- }
- }
-
- void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
- if (oldAdapter != null) {
- oldAdapter.unregisterDataSetObserver(mPageListener);
- mWatchingAdapter = null;
- }
-
- if (newAdapter != null) {
- newAdapter.registerDataSetObserver(mPageListener);
- mWatchingAdapter = new WeakReference<>(newAdapter);
- }
-
- updateDots();
-
- if (mPager != null) {
- requestLayout();
- }
- }
-
- private <T> T getRef(WeakReference<T> weakRef) {
- if (weakRef == null) {
- return null;
- }
- return weakRef.get();
- }
-
- private void updateDots() {
- PagerAdapter adapter = getRef(mWatchingAdapter);
- if (adapter == null) {
- return;
- }
-
- int count = adapter.getCount();
- if (mPageCount == count) {
- // Nothing to be done.
- return;
- }
-
- mPageCount = count;
- mCurrentPosition = 0;
- invalidate();
- }
-
- private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
- ViewPager.OnAdapterChangeListener {
-
- @Override
- public void onPageScrolled(int unused1, float unused2, int unused3) { }
-
- @Override
- public void onPageSelected(int position) {
- if (mCurrentPosition == position) {
- return;
- }
-
- if (mPageCount <= position) {
- Log.e(TAG, "Position out of bounds, position=" + position + " size=" + mPageCount);
- return;
- }
-
- mCurrentPosition = position;
- invalidate();
- }
-
- @Override
- public void onPageScrollStateChanged(int state) { }
-
- @Override
- public void onAdapterChanged(ViewPager viewPager, PagerAdapter oldAdapter,
- PagerAdapter newAdapter) {
- updateAdapter(oldAdapter, newAdapter);
- }
-
- @Override
- public void onChanged() {
- updateDots();
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 5ad08ac..a171468 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -263,13 +263,13 @@
GradientDrawable shape = new GradientDrawable();
shape.setShape(GradientDrawable.RADIAL_GRADIENT);
shape.setGradientRadius(1.0f);
- shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
+ shape.setColor(mContext.getColor(R.color.car_grey_50));
shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
shape.draw(canvas);
// Draw the letter in the center.
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
+ paint.setColor(mContext.getColor(R.color.car_grey_900));
paint.setTextAlign(Align.CENTER);
if (isAddUserText) {
paint.setTextSize(mRes.getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 3e7b0d9..420c517 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -50,6 +50,7 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenModeConfig;
import android.telecom.TelecomManager;
import android.util.ArraySet;
import android.util.Log;
@@ -287,6 +288,11 @@
}
@Override
+ public void onConfigChanged(ZenModeConfig config) {
+ updateVolumeZen();
+ }
+
+ @Override
public void onLocationActiveChanged(boolean active) {
updateLocation();
}
@@ -363,16 +369,16 @@
zenDescription = mContext.getString(R.string.interruption_level_priority);
}
- if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
- audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_vibrate;
- volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
- } else if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
- audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_silent;
- volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
+ if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConfig())) {
+ if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
+ volumeVisible = true;
+ volumeIconId = R.drawable.stat_sys_ringer_vibrate;
+ volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
+ } else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
+ volumeVisible = true;
+ volumeIconId = R.drawable.stat_sys_ringer_silent;
+ volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
+ }
}
if (zenVisible) {
diff --git a/packages/VpnDialogs/res/values-cs/strings.xml b/packages/VpnDialogs/res/values-cs/strings.xml
index 47d950f..5cc809c 100644
--- a/packages/VpnDialogs/res/values-cs/strings.xml
+++ b/packages/VpnDialogs/res/values-cs/strings.xml
@@ -25,8 +25,8 @@
<string name="data_received" msgid="4062776929376067820">"Přijato:"</string>
<string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bajtů / <xliff:g id="NUMBER_1">%2$s</xliff:g> paketů"</string>
<string name="always_on_disconnected_title" msgid="1906740176262776166">"Nelze se připojit k trvalé VPN"</string>
- <string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikace <xliff:g id="VPN_APP_0">%1$s</xliff:g> je nastavena k trvalému připojení, ale nyní se nemůže připojit. Než se telefon bude moci připojit pomocí aplikace <xliff:g id="VPN_APP_1">%1$s</xliff:g>, použije veřejnou síť."</string>
- <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikace <xliff:g id="VPN_APP">%1$s</xliff:g> je nastavena k trvalému připojení, ale nyní se nemůže připojit. Než se budete moci připojit pomocí VPN, zůstanete offline."</string>
+ <string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikace <xliff:g id="VPN_APP_0">%1$s</xliff:g> je nastavena k trvalému připojení, ale teď se nemůže připojit. Než se telefon bude moci připojit pomocí aplikace <xliff:g id="VPN_APP_1">%1$s</xliff:g>, použije veřejnou síť."</string>
+ <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikace <xliff:g id="VPN_APP">%1$s</xliff:g> je nastavena k trvalému připojení, ale teď se nemůže připojit. Než se budete moci připojit pomocí VPN, zůstanete offline."</string>
<string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string>
<string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Změnit nastavení VPN"</string>
<string name="configure" msgid="4905518375574791375">"Konfigurovat"</string>
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6463bed..079d815 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1383,7 +1383,8 @@
if (nai != null) {
synchronized (nai) {
if (nai.networkCapabilities != null) {
- return networkCapabilitiesWithoutUidsUnlessAllowed(nai.networkCapabilities,
+ return networkCapabilitiesRestrictedForCallerPermissions(
+ nai.networkCapabilities,
Binder.getCallingPid(), Binder.getCallingUid());
}
}
@@ -1397,10 +1398,12 @@
return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
}
- private NetworkCapabilities networkCapabilitiesWithoutUidsUnlessAllowed(
+ private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
NetworkCapabilities nc, int callerPid, int callerUid) {
- if (checkSettingsPermission(callerPid, callerUid)) return new NetworkCapabilities(nc);
- return new NetworkCapabilities(nc).setUids(null);
+ final NetworkCapabilities newNc = new NetworkCapabilities(nc);
+ if (!checkSettingsPermission(callerPid, callerUid)) newNc.setUids(null);
+ if (!checkNetworkStackPermission(callerPid, callerUid)) newNc.setSSID(null);
+ return newNc;
}
private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
@@ -1659,6 +1662,11 @@
android.Manifest.permission.NETWORK_SETTINGS, pid, uid);
}
+ private boolean checkNetworkStackPermission(int pid, int uid) {
+ return PERMISSION_GRANTED == mContext.checkPermission(
+ android.Manifest.permission.NETWORK_STACK, pid, uid);
+ }
+
private void enforceTetherAccessPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -4235,6 +4243,15 @@
}
}
+ // This checks that the passed capabilities either do not request a specific SSID, or the
+ // calling app has permission to do so.
+ private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
+ int callerPid, int callerUid) {
+ if (null != nc.getSSID() && !checkNetworkStackPermission(callerPid, callerUid)) {
+ throw new SecurityException("Insufficient permissions to request a specific SSID");
+ }
+ }
+
private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
final SortedSet<Integer> thresholds = new TreeSet();
synchronized (nai) {
@@ -4304,6 +4321,8 @@
enforceMeteredApnPolicy(networkCapabilities);
}
ensureRequestableCapabilities(networkCapabilities);
+ ensureSufficientPermissionsForRequest(networkCapabilities,
+ Binder.getCallingPid(), Binder.getCallingUid());
// Set the UID range for this request to the single UID of the requester, or to an empty
// set of UIDs if the caller has the appropriate permission and UIDs have not been set.
// This will overwrite any allowed UIDs in the requested capabilities. Though there
@@ -4382,6 +4401,8 @@
enforceNetworkRequestPermissions(networkCapabilities);
enforceMeteredApnPolicy(networkCapabilities);
ensureRequestableCapabilities(networkCapabilities);
+ ensureSufficientPermissionsForRequest(networkCapabilities,
+ Binder.getCallingPid(), Binder.getCallingUid());
ensureValidNetworkSpecifier(networkCapabilities);
restrictRequestUidsForCaller(networkCapabilities);
@@ -4437,6 +4458,8 @@
}
NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
+ ensureSufficientPermissionsForRequest(networkCapabilities,
+ Binder.getCallingPid(), Binder.getCallingUid());
restrictRequestUidsForCaller(nc);
// Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
// make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
@@ -4463,6 +4486,8 @@
enforceAccessPermission();
}
ensureValidNetworkSpecifier(networkCapabilities);
+ ensureSufficientPermissionsForRequest(networkCapabilities,
+ Binder.getCallingPid(), Binder.getCallingUid());
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
restrictRequestUidsForCaller(nc);
@@ -5034,7 +5059,7 @@
}
case ConnectivityManager.CALLBACK_CAP_CHANGED: {
// networkAgent can't be null as it has been accessed a few lines above.
- final NetworkCapabilities nc = networkCapabilitiesWithoutUidsUnlessAllowed(
+ final NetworkCapabilities nc = networkCapabilitiesRestrictedForCallerPermissions(
networkAgent.networkCapabilities, nri.mPid, nri.mUid);
putParcelable(bundle, nc);
break;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index fb5fba0..d4290ee 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -960,7 +960,8 @@
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
- getResolutionPermission(mAllowedResolutionLevel));
+ getResolutionPermission(mAllowedResolutionLevel),
+ PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -995,7 +996,8 @@
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
- getResolutionPermission(mAllowedResolutionLevel));
+ getResolutionPermission(mAllowedResolutionLevel),
+ PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -1037,7 +1039,8 @@
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
- getResolutionPermission(mAllowedResolutionLevel));
+ getResolutionPermission(mAllowedResolutionLevel),
+ PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
diff --git a/services/core/java/com/android/server/PendingIntentUtils.java b/services/core/java/com/android/server/PendingIntentUtils.java
new file mode 100644
index 0000000..1600101
--- /dev/null
+++ b/services/core/java/com/android/server/PendingIntentUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.server;
+
+import android.annotation.Nullable;
+import android.app.BroadcastOptions;
+import android.os.Bundle;
+
+/**
+ * Some utility methods for system server.
+ * @hide
+ */
+public class PendingIntentUtils {
+ /**
+ * Creates a Bundle that can be used to restrict the background PendingIntents.
+ * @param bundle when provided, will merge the extra options to restrict background
+ * PendingIntent into the existing bundle.
+ * @return the created Bundle.
+ */
+ public static Bundle createDontSendToRestrictedAppsBundle(@Nullable Bundle bundle) {
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setDontSendToRestrictedApps(true);
+ if (bundle == null) {
+ return options.toBundle();
+ }
+ bundle.putAll(options.toBundle());
+ return bundle;
+ }
+
+ // Disable the constructor.
+ private PendingIntentUtils() {}
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 47284cb..f620c77 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6771,6 +6771,13 @@
int[] users = userId == UserHandle.USER_ALL
? mUserController.getUsers() : new int[] { userId };
for (int user : users) {
+ if (getPackageManagerInternalLocked().isPackageStateProtected(
+ packageName, user)) {
+ Slog.w(TAG, "Ignoring request to force stop protected package "
+ + packageName + " u" + user);
+ return;
+ }
+
int pkgUid = -1;
try {
pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING,
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
new file mode 100644
index 0000000..e34ee63
--- /dev/null
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 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.server.am;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.GradientDrawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
+ * screen immediately after the dialog shows so that the user is informed that something is
+ * happening in the background rather than just freeze the screen and not know if the user-switch
+ * affordance was being handled.
+ *
+ */
+final class CarUserSwitchingDialog extends UserSwitchingDialog {
+ private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
+
+ public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
+ UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
+ String switchingToSystemUserMessage) {
+ super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
+ switchingToSystemUserMessage);
+
+ getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ }
+
+ @Override
+ void inflateContent() {
+ // Set up the dialog contents
+ setCancelable(false);
+ Resources res = getContext().getResources();
+ // Custom view due to alignment and font size requirements
+ View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
+ null);
+
+ ((ImageView) view.findViewById(R.id.user_loading_avatar))
+ .setImageBitmap(getDefaultUserIcon(mNewUser));
+ ((TextView) view.findViewById(R.id.user_loading))
+ .setText(res.getString(R.string.car_loading_profile));
+ setView(view);
+ }
+
+ /**
+ * Returns the default user icon. This icon is a circle with a letter in it. The letter is
+ * the first character in the username.
+ *
+ * @param userInfo the profile of the user for which the icon should be created
+ */
+ private Bitmap getDefaultUserIcon(UserInfo userInfo) {
+ Resources res = mContext.getResources();
+ int mPodImageAvatarWidth = res.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_image_avatar_width);
+ int mPodImageAvatarHeight = res.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_image_avatar_height);
+ CharSequence displayText = userInfo.name.subSequence(0, 1);
+ Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(out);
+
+ // Draw the circle background.
+ GradientDrawable shape = new GradientDrawable();
+ shape.setShape(GradientDrawable.RADIAL_GRADIENT);
+ shape.setGradientRadius(1.0f);
+ shape.setColor(mContext.getColor(R.color.car_user_switcher_user_image_bgcolor));
+ shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
+ shape.draw(canvas);
+
+ // Draw the letter in the center.
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setColor(mContext.getColor(R.color.car_user_switcher_user_image_fgcolor));
+ paint.setTextAlign(Align.CENTER);
+ paint.setTextSize(res.getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_icon_text_size));
+
+ Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
+ // The Y coordinate is measured by taking half the height of the pod, but that would
+ // draw the character putting the bottom of the font in the middle of the pod. To
+ // correct this, half the difference between the top and bottom distance metrics of the
+ // font gives the offset of the font. Bottom is a positive value, top is negative, so
+ // the different is actually a sum. The "half" operation is then factored out.
+ canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
+ (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
+
+ return out;
+ }
+}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index fecb934..060d4c8 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -79,6 +79,7 @@
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.IntArray;
+import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -86,6 +87,7 @@
import android.util.TimingsTraceLog;
import android.util.proto.ProtoOutputStream;
+import android.view.Window;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -2177,9 +2179,18 @@
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
- Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
+ Dialog d;
+ if (!mService.mContext.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
true /* above system */, switchingFromSystemUserMessage,
switchingToSystemUserMessage);
+ } else {
+ d = new CarUserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
+ true /* above system */, switchingFromSystemUserMessage,
+ switchingToSystemUserMessage);
+ }
+
d.show();
}
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index afcba3b..98f5557 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -39,7 +39,7 @@
* in the background rather than just freeze the screen and not know if the user-switch affordance
* was being handled.
*/
-final class UserSwitchingDialog extends AlertDialog
+class UserSwitchingDialog extends AlertDialog
implements ViewTreeObserver.OnWindowShownListener {
private static final String TAG = "ActivityManagerUserSwitchingDialog";
@@ -51,53 +51,69 @@
private static final int MSG_START_USER = 1;
@GuardedBy("this")
private boolean mStartedUser;
+ final protected UserInfo mOldUser;
+ final protected UserInfo mNewUser;
+ final private String mSwitchingFromSystemUserMessage;
+ final private String mSwitchingToSystemUserMessage;
+ final protected Context mContext;
public UserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
String switchingToSystemUserMessage) {
super(context);
+ mContext = context;
mService = service;
mUserId = newUser.id;
+ mOldUser = oldUser;
+ mNewUser = newUser;
+ mSwitchingFromSystemUserMessage = switchingFromSystemUserMessage;
+ mSwitchingToSystemUserMessage = switchingToSystemUserMessage;
+ inflateContent();
+
+ if (aboveSystem) {
+ getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ }
+
+ WindowManager.LayoutParams attrs = getWindow().getAttributes();
+ attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ getWindow().setAttributes(attrs);
+ }
+
+ void inflateContent() {
// Set up the dialog contents
setCancelable(false);
Resources res = getContext().getResources();
// Custom view due to alignment and font size requirements
- View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog, null);
+ View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog,
+ null);
String viewMessage = null;
- if (UserManager.isSplitSystemUser() && newUser.id == UserHandle.USER_SYSTEM) {
- viewMessage = res.getString(R.string.user_logging_out_message, oldUser.name);
- } else if (UserManager.isDeviceInDemoMode(context)) {
- if (oldUser.isDemo()) {
+ if (UserManager.isSplitSystemUser() && mNewUser.id == UserHandle.USER_SYSTEM) {
+ viewMessage = res.getString(R.string.user_logging_out_message, mOldUser.name);
+ } else if (UserManager.isDeviceInDemoMode(mContext)) {
+ if (mOldUser.isDemo()) {
viewMessage = res.getString(R.string.demo_restarting_message);
} else {
viewMessage = res.getString(R.string.demo_starting_message);
}
} else {
- if (oldUser.id == UserHandle.USER_SYSTEM) {
- viewMessage = switchingFromSystemUserMessage;
- } else if (newUser.id == UserHandle.USER_SYSTEM) {
- viewMessage = switchingToSystemUserMessage;
+ if (mOldUser.id == UserHandle.USER_SYSTEM) {
+ viewMessage = mSwitchingFromSystemUserMessage;
+ } else if (mNewUser.id == UserHandle.USER_SYSTEM) {
+ viewMessage = mSwitchingToSystemUserMessage;
}
// If switchingFromSystemUserMessage or switchingToSystemUserMessage is null, fallback
// to system message.
if (viewMessage == null) {
- viewMessage = res.getString(R.string.user_switching_message, newUser.name);
+ viewMessage = res.getString(R.string.user_switching_message, mNewUser.name);
}
}
((TextView) view.findViewById(R.id.message)).setText(viewMessage);
setView(view);
-
- if (aboveSystem) {
- getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
- }
- WindowManager.LayoutParams attrs = getWindow().getAttributes();
- attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- getWindow().setAttributes(attrs);
}
@Override
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index ca8823f..0ee55ed 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -165,12 +165,22 @@
private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
@Override
public void pingForUserUpdate() {
+ if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
+ Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " +
+ " camera service UID!");
+ return;
+ }
notifySwitchWithRetries(30);
}
@Override
public void notifyCameraState(String cameraId, int newCameraState, int facing,
String clientName, int apiLevel) {
+ if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
+ Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " +
+ " camera service UID!");
+ return;
+ }
String state = cameraStateToString(newCameraState);
String facingStr = cameraFacingToString(facing);
if (DEBUG) Slog.v(TAG, "Camera " + cameraId + " facing " + facingStr + " state now " +
@@ -301,7 +311,12 @@
}
mCameraUsageHistory.clear();
}
- CameraStatsJobService.schedule(mContext);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ CameraStatsJobService.schedule(mContext);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
private void switchUserLocked(int userHandle) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 0d935db..02459bd 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.content.res.Resources;
import android.net.NetworkCapabilities;
+import android.net.wifi.WifiInfo;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -176,7 +177,8 @@
switch (transportType) {
case TRANSPORT_WIFI:
title = r.getString(R.string.wifi_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed, extraInfo);
+ details = r.getString(R.string.network_available_sign_in_detailed,
+ WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
break;
case TRANSPORT_CELLULAR:
title = r.getString(R.string.network_available_sign_in, 0);
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index d50ffe9..fafe99c 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -42,6 +42,7 @@
import android.util.Slog;
import com.android.server.LocationManagerService;
+import com.android.server.PendingIntentUtils;
public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
private static final String TAG = "GeofenceManager";
@@ -401,7 +402,8 @@
mWakeLock.acquire();
try {
pendingIntent.send(mContext, 0, intent, this, null,
- android.Manifest.permission.ACCESS_FINE_LOCATION);
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
} catch (PendingIntent.CanceledException e) {
removeFence(null, pendingIntent);
mWakeLock.release();
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 1faa9f7..5d71cc7 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -70,8 +70,6 @@
private static final String LOCK_SCREEN_HASH_ALGORITHM = "SHA-256";
private static final int TRUSTED_HARDWARE_MAX_ATTEMPTS = 10;
- // TODO: Reduce the minimal length once all other components are updated
- private static final int MIN_CREDENTIAL_LEN_TO_USE_SCRYPT = 24;
@VisibleForTesting
static final int SCRYPT_PARAM_N = 4096;
@VisibleForTesting
@@ -246,7 +244,7 @@
}
}
- boolean useScryptToHashCredential = shouldUseScryptToHashCredential(rootCertAlias);
+ boolean useScryptToHashCredential = shouldUseScryptToHashCredential();
byte[] salt = generateSalt();
byte[] localLskfHash;
if (useScryptToHashCredential) {
@@ -514,10 +512,7 @@
return keyEntries;
}
- private boolean shouldUseScryptToHashCredential(String rootCertAlias) {
- return mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
- && mCredential.length() >= MIN_CREDENTIAL_LEN_TO_USE_SCRYPT
- // TODO: Remove the test cert check once all other components are updated
- && mTestOnlyInsecureCertificateHelper.isTestOnlyCertificateAlias(rootCertAlias);
+ private boolean shouldUseScryptToHashCredential() {
+ return mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a047604..57c2b75 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -23856,6 +23856,11 @@
}
@Override
+ public boolean isPackageStateProtected(String packageName, int userId) {
+ return mProtectedPackages.isPackageStateProtected(userId, packageName);
+ }
+
+ @Override
public boolean isPackageEphemeral(int userId, String packageName) {
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 46a636c..fce4b20 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2550,6 +2550,7 @@
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
if (ActivityManager.isHighEndGfx()) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
lp.privateFlags |=
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index b7b9612..a9cdafd 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -44,7 +44,6 @@
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
-import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -52,7 +51,6 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
-import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml.Encoding;
@@ -71,9 +69,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -136,11 +132,16 @@
@Override
public Uri[] getPinnedSlices(String pkg) {
verifyCaller(pkg);
+ int callingUser = Binder.getCallingUserHandle().getIdentifier();
ArrayList<Uri> ret = new ArrayList<>();
synchronized (mLock) {
for (PinnedSliceState state : mPinnedSlicesByUri.values()) {
if (Objects.equals(pkg, state.getPkg())) {
- ret.add(state.getUri());
+ Uri uri = state.getUri();
+ int userId = ContentProvider.getUserIdFromUri(uri, callingUser);
+ if (userId == callingUser) {
+ ret.add(ContentProvider.getUriWithoutUserId(uri));
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 1ee642a..6478632 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -549,7 +549,12 @@
@Override
public void startAnimation(SurfaceControl animationLeash, Transaction t,
OnAnimationFinishedCallback finishCallback) {
+ // Restore z-layering, position and stack crop until client has a chance to modify it.
+ t.setLayer(animationLeash, mTask.getPrefixOrderIndex());
t.setPosition(animationLeash, mPosition.x, mPosition.y);
+ mTmpRect.set(mBounds);
+ mTmpRect.offsetTo(0, 0);
+ t.setWindowCrop(animationLeash, mTmpRect);
mCapturedLeash = animationLeash;
mCapturedFinishCallback = finishCallback;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 0e5b7b3..a9d6c29 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -92,8 +92,8 @@
new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
private static final String TEST_APP_KEY_ALIAS = "rcleaver";
private static final int TEST_GENERATION_ID = 2;
- private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PASSWORD;
- private static final String TEST_CREDENTIAL = "password1234";
+ private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PATTERN;
+ private static final String TEST_CREDENTIAL = "pas123";
private static final byte[] THM_ENCRYPTED_RECOVERY_KEY_HEADER =
"V1 THM_encrypted_recovery_key".getBytes(StandardCharsets.UTF_8);
@@ -278,8 +278,8 @@
}
@Test
- public void run_useScryptToHashLongPasswordInTestMode() throws Exception {
- String longPassword = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "0123456789";
+ public void run_useScryptToHashPasswordInTestMode() throws Exception {
+ String password = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + ""; // The shortest
String appKeyAlias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "alias";
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
@@ -287,7 +287,7 @@
mSnapshotListenersStorage,
TEST_USER_ID,
CREDENTIAL_TYPE_PASSWORD,
- /*credential=*/ longPassword,
+ /*credential=*/ password,
/*credentialUpdated=*/ false,
mPlatformKeyManager,
mTestOnlyInsecureCertificateHelper,
@@ -309,7 +309,7 @@
assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
isEqualTo(UI_FORMAT_PASSWORD);
- verify(mMockScrypt).scrypt(eq(longPassword.getBytes()), any(),
+ verify(mMockScrypt).scrypt(eq(password.getBytes()), any(),
eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
KeyDerivationParams keyDerivationParams =
@@ -320,16 +320,15 @@
}
@Test
- public void run_useSha256ToHashShortPasswordInTestMode() throws Exception {
- String shortPassword = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "012345678";
- String appKeyAlias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "alias";
+ public void run_useSha256ToHashPatternInProdMode() throws Exception {
+ String pattern = "123456";
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
mRecoverySnapshotStorage,
mSnapshotListenersStorage,
TEST_USER_ID,
- CREDENTIAL_TYPE_PASSWORD,
- /*credential=*/ shortPassword,
+ CREDENTIAL_TYPE_PATTERN,
+ /*credential=*/ pattern,
/*credentialUpdated=*/ false,
mPlatformKeyManager,
mTestOnlyInsecureCertificateHelper,
@@ -337,20 +336,16 @@
mRecoverableKeyStoreDb.setServerParams(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
- mRecoverableKeyStoreDb.setActiveRootOfTrust(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
- TrustedRootCertificates.TEST_ONLY_INSECURE_CERTIFICATE_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
- TrustedRootCertificates.TEST_ONLY_INSECURE_CERTIFICATE_ALIAS,
- TestData.getInsecureCertPathForEndpoint1());
- addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, appKeyAlias);
+ TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
mKeySyncTask.run();
KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
- isEqualTo(UI_FORMAT_PASSWORD);
+ isEqualTo(UI_FORMAT_PATTERN);
verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
KeyDerivationParams keyDerivationParams =
keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
@@ -359,8 +354,8 @@
}
@Test
- public void run_useSha256ToHashShortPasswordInProdMode() throws Exception {
- String shortPassword = "01234567890123456789abc"; // 23 chars
+ public void run_useScryptToHashPasswordInProdMode() throws Exception {
+ String shortPassword = "abc";
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
mRecoverySnapshotStorage,
@@ -385,45 +380,13 @@
assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
isEqualTo(UI_FORMAT_PASSWORD);
- verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
+ verify(mMockScrypt).scrypt(eq(shortPassword.getBytes()), any(),
+ eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
+ eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
KeyDerivationParams keyDerivationParams =
keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
assertThat(keyDerivationParams.getAlgorithm()).isEqualTo(
- KeyDerivationParams.ALGORITHM_SHA256);
- }
-
- @Test
- public void run_useSha256ToHashLongPasswordInProdMode() throws Exception {
- String longPassword = "01234567890123456789abcd"; // 24 chars
- mKeySyncTask = new KeySyncTask(
- mRecoverableKeyStoreDb,
- mRecoverySnapshotStorage,
- mSnapshotListenersStorage,
- TEST_USER_ID,
- CREDENTIAL_TYPE_PASSWORD,
- /*credential=*/ longPassword,
- /*credentialUpdated=*/ false,
- mPlatformKeyManager,
- mTestOnlyInsecureCertificateHelper,
- mMockScrypt);
- mRecoverableKeyStoreDb.setServerParams(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
- mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
- addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
- mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
- TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
-
- mKeySyncTask.run();
-
- KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
- assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
- assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
- isEqualTo(UI_FORMAT_PASSWORD);
- verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
- KeyDerivationParams keyDerivationParams =
- keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
- assertThat(keyDerivationParams.getAlgorithm()).isEqualTo(
- KeyDerivationParams.ALGORITHM_SHA256);
+ KeyDerivationParams.ALGORITHM_SCRYPT);
}
@Test
@@ -644,13 +607,14 @@
@Test
public void run_setsCorrectTypeForPassword() throws Exception {
+ String password = "password";
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
mRecoverySnapshotStorage,
mSnapshotListenersStorage,
TEST_USER_ID,
CREDENTIAL_TYPE_PASSWORD,
- "password",
+ password,
/*credentialUpdated=*/ false,
mPlatformKeyManager,
mTestOnlyInsecureCertificateHelper,
@@ -659,8 +623,7 @@
mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
- SecretKey applicationKey =
- addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+ addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
mKeySyncTask.run();
@@ -668,18 +631,21 @@
assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
isEqualTo(UI_FORMAT_PASSWORD);
- verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
+ verify(mMockScrypt).scrypt(eq(password.getBytes()), any(),
+ eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
+ eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
}
@Test
public void run_setsCorrectTypeForPin() throws Exception {
+ String pin = "1234";
mKeySyncTask = new KeySyncTask(
mRecoverableKeyStoreDb,
mRecoverySnapshotStorage,
mSnapshotListenersStorage,
TEST_USER_ID,
CREDENTIAL_TYPE_PASSWORD,
- /*credential=*/ "1234",
+ /*credential=*/ pin,
/*credentialUpdated=*/ false,
mPlatformKeyManager,
mTestOnlyInsecureCertificateHelper,
@@ -698,7 +664,9 @@
// Password with only digits is changed to pin.
assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
isEqualTo(UI_FORMAT_PIN);
- verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
+ verify(mMockScrypt).scrypt(eq(pin.getBytes()), any(),
+ eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
+ eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
}
@Test
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index cdb4307..da897ae 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -39,12 +39,14 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,6 +55,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NetworkCapabilitiesTest {
+ private static final String TEST_SSID = "TEST_SSID";
+
@Test
public void testMaybeMarkCapabilitiesRestricted() {
// verify EIMS is restricted
@@ -259,6 +263,8 @@
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
assertEqualsThroughMarshalling(netCap);
+ netCap.setSSID(TEST_SSID);
+ assertEqualsThroughMarshalling(netCap);
}
@Test
@@ -354,6 +360,21 @@
}
@Test
+ public void testSSID() {
+ NetworkCapabilities nc1 = new NetworkCapabilities();
+ NetworkCapabilities nc2 = new NetworkCapabilities();
+ assertTrue(nc2.satisfiedBySSID(nc1));
+
+ nc1.setSSID(TEST_SSID);
+ assertTrue(nc2.satisfiedBySSID(nc1));
+ nc2.setSSID("different " + TEST_SSID);
+ assertFalse(nc2.satisfiedBySSID(nc1));
+
+ assertTrue(nc1.satisfiedByImmutableNetworkCapabilities(nc2));
+ assertFalse(nc1.satisfiedByNetworkCapabilities(nc2));
+ }
+
+ @Test
public void testCombineCapabilities() {
NetworkCapabilities nc1 = new NetworkCapabilities();
NetworkCapabilities nc2 = new NetworkCapabilities();
@@ -374,6 +395,19 @@
// will never be satisfied.
assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+
+ nc1.setSSID(TEST_SSID);
+ nc2.combineCapabilities(nc1);
+ assertTrue(TEST_SSID.equals(nc2.getSSID()));
+
+ // Because they now have the same SSID, the folllowing call should not throw
+ nc2.combineCapabilities(nc1);
+
+ nc1.setSSID("different " + TEST_SSID);
+ try {
+ nc2.combineCapabilities(nc1);
+ fail("Expected IllegalStateException: can't combine different SSIDs");
+ } catch (IllegalStateException expected) {}
}
@Test