Merge "Support logging intents from Profile select dialog" into rvc-dev
diff --git a/Android.mk b/Android.mk
index aea0c95..3b30714 100644
--- a/Android.mk
+++ b/Android.mk
@@ -39,11 +39,6 @@
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
-$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE):apistubs/android/public/api/android.txt)
-$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE):apistubs/android/system/api/android.txt)
-$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE):apistubs/android/test/api/android.txt)
-$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_MODULE_LIB_API_FILE):apistubs/android/module-lib/api/android.txt)
-$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_SERVER_API_FILE):apistubs/android/system-server/api/android.txt)
# sdk.atree needs to copy the whole dir: $(OUT_DOCS)/offline-sdk to the final zip.
# So keep offline-sdk-timestamp target here, and unzip offline-sdk-docs.zip to
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 12f211d..ccd87335 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -115,6 +115,11 @@
baseline_file: "api/lint-baseline.txt",
},
},
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/public/api",
+ dest: "android.txt",
+ },
jdiff_enabled: true,
}
@@ -156,6 +161,11 @@
baseline_file: "api/system-lint-baseline.txt",
},
},
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system/api",
+ dest: "android.txt",
+ },
jdiff_enabled: true,
}
@@ -179,6 +189,11 @@
baseline_file: "api/test-lint-baseline.txt",
},
},
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/test/api",
+ dest: "android.txt",
+ },
}
/////////////////////////////////////////////////////////////////////
@@ -214,6 +229,11 @@
baseline_file: "api/module-lib-lint-baseline.txt",
},
},
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/module-lib/api",
+ dest: "android.txt",
+ },
}
diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp
index 6d96200..3fefeb5 100644
--- a/apex/permission/framework/Android.bp
+++ b/apex/permission/framework/Android.bp
@@ -84,20 +84,17 @@
java_library {
name: "framework-permission-stubs-publicapi",
srcs: [ ":framework-permission-stubs-srcs-publicapi" ],
- sdk_version: "system_current",
- installable: false,
+ defaults: ["framework-module-stubs-lib-defaults-publicapi"],
}
java_library {
name: "framework-permission-stubs-systemapi",
srcs: [ ":framework-permission-stubs-srcs-systemapi" ],
- sdk_version: "system_current",
- installable: false,
+ defaults: ["framework-module-stubs-lib-defaults-systemapi"],
}
java_library {
name: "framework-permission-stubs-module_libs_api",
srcs: [ ":framework-permission-stubs-srcs-module_libs_api" ],
- sdk_version: "system_current",
- installable: false,
+ defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
}
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 8185bb0..804eb03 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -46,19 +46,11 @@
"//frameworks/base/apex/statsd:__subpackages__",
],
}
-
-java_defaults {
- name: "framework-statsd-defaults",
- sdk_version: "module_current",
- libs: [ "framework-annotations-lib" ],
-}
-
java_library {
name: "framework-statsd",
- defaults: [
- "framework-statsd-defaults",
- ],
installable: true,
+ sdk_version: "module_current",
+ libs: [ "framework-annotations-lib" ],
srcs: [
":framework-statsd-sources",
@@ -129,39 +121,33 @@
java_library {
name: "framework-statsd-stubs-publicapi",
- defaults: [
- "framework-statsd-defaults",
- ],
+ defaults: ["framework-module-stubs-lib-defaults-publicapi"],
srcs: [ ":framework-statsd-stubs-srcs-publicapi" ],
visibility: [
"//frameworks/base", // Framework
"//frameworks/base/apex/statsd", // statsd apex
- ]
+ ],
}
java_library {
name: "framework-statsd-stubs-systemapi",
- defaults: [
- "framework-statsd-defaults",
- ],
+ defaults: ["framework-module-stubs-lib-defaults-systemapi"],
srcs: [ ":framework-statsd-stubs-srcs-systemapi" ],
visibility: [
"//frameworks/base", // Framework
"//frameworks/base/apex/statsd", // statsd apex
- ]
+ ],
}
java_library {
name: "framework-statsd-stubs-module_libs_api",
- defaults: [
- "framework-statsd-defaults",
- ],
+ defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
srcs: [ ":framework-statsd-stubs-srcs-module_libs_api" ],
visibility: [
"//frameworks/base", // Framework
"//frameworks/base/apex/statsd", // statsd apex
"//frameworks/opt/net/wifi/service" // wifi service
- ]
+ ],
}
android_test {
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 59544a9..ca1d598 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -32,8 +32,11 @@
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.Pair;
import java.io.FileDescriptor;
+import java.util.ArrayList;
+import java.util.List;
/**
* This class is a command line utility for manipulating content. A client
@@ -72,7 +75,7 @@
"usage: adb shell content [subcommand] [options]\n"
+ "\n"
+ "usage: adb shell content insert --uri <URI> [--user <USER_ID>]"
- + " --bind <BINDING> [--bind <BINDING>...]\n"
+ + " --bind <BINDING> [--bind <BINDING>...] [--extra <BINDING>...]\n"
+ " <URI> a content provider URI.\n"
+ " <BINDING> binds a typed value to a column and is formatted:\n"
+ " <COLUMN_NAME>:<TYPE>:<COLUMN_VALUE> where:\n"
@@ -84,7 +87,8 @@
+ " adb shell content insert --uri content://settings/secure --bind name:s:new_setting"
+ " --bind value:s:new_value\n"
+ "\n"
- + "usage: adb shell content update --uri <URI> [--user <USER_ID>] [--where <WHERE>]\n"
+ + "usage: adb shell content update --uri <URI> [--user <USER_ID>]"
+ + " [--where <WHERE>] [--extra <BINDING>...]\n"
+ " <WHERE> is a SQL style where clause in quotes (You have to escape single quotes"
+ " - see example below).\n"
+ " Example:\n"
@@ -93,14 +97,15 @@
+ " value:s:newer_value --where \"name=\'new_setting\'\"\n"
+ "\n"
+ "usage: adb shell content delete --uri <URI> [--user <USER_ID>] --bind <BINDING>"
- + " [--bind <BINDING>...] [--where <WHERE>]\n"
+ + " [--bind <BINDING>...] [--where <WHERE>] [--extra <BINDING>...]\n"
+ " Example:\n"
+ " # Remove \"new_setting\" secure setting.\n"
+ " adb shell content delete --uri content://settings/secure "
+ "--where \"name=\'new_setting\'\"\n"
+ "\n"
+ "usage: adb shell content query --uri <URI> [--user <USER_ID>]"
- + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
+ + " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]"
+ + " [--extra <BINDING>...]\n"
+ " <PROJECTION> is a list of colon separated column names and is formatted:\n"
+ " <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
+ " <SORT_ORDER> is the order in which rows in the result should be sorted.\n"
@@ -196,6 +201,7 @@
Uri uri = null;
int userId = UserHandle.USER_SYSTEM;
ContentValues values = new ContentValues();
+ Bundle extras = new Bundle();
for (String argument; (argument = mTokenizer.nextArg()) != null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
@@ -203,6 +209,8 @@
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_BIND.equals(argument)) {
parseBindValue(values);
+ } else if (ARGUMENT_EXTRA.equals(argument)) {
+ parseBindValue(extras);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
@@ -215,20 +223,23 @@
throw new IllegalArgumentException("Bindings not specified."
+ " Did you specify --bind argument(s)?");
}
- return new InsertCommand(uri, userId, values);
+ return new InsertCommand(uri, userId, values, extras);
}
private DeleteCommand parseDeleteCommand() {
Uri uri = null;
int userId = UserHandle.USER_SYSTEM;
- String where = null;
+ Bundle extras = new Bundle();
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_WHERE.equals(argument)) {
- where = argumentValueRequired(argument);
+ extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION,
+ argumentValueRequired(argument));
+ } else if (ARGUMENT_EXTRA.equals(argument)) {
+ parseBindValue(extras);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
@@ -237,23 +248,26 @@
throw new IllegalArgumentException("Content provider URI not specified."
+ " Did you specify --uri argument?");
}
- return new DeleteCommand(uri, userId, where);
+ return new DeleteCommand(uri, userId, extras);
}
private UpdateCommand parseUpdateCommand() {
Uri uri = null;
int userId = UserHandle.USER_SYSTEM;
- String where = null;
ContentValues values = new ContentValues();
+ Bundle extras = new Bundle();
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_WHERE.equals(argument)) {
- where = argumentValueRequired(argument);
+ extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION,
+ argumentValueRequired(argument));
} else if (ARGUMENT_BIND.equals(argument)) {
parseBindValue(values);
+ } else if (ARGUMENT_EXTRA.equals(argument)) {
+ parseBindValue(extras);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
@@ -266,7 +280,7 @@
throw new IllegalArgumentException("Bindings not specified."
+ " Did you specify --bind argument(s)?");
}
- return new UpdateCommand(uri, userId, values, where);
+ return new UpdateCommand(uri, userId, values, extras);
}
public CallCommand parseCallCommand() {
@@ -274,7 +288,7 @@
int userId = UserHandle.USER_SYSTEM;
String arg = null;
Uri uri = null;
- ContentValues values = new ContentValues();
+ Bundle extras = new Bundle();
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
@@ -285,11 +299,10 @@
} else if (ARGUMENT_ARG.equals(argument)) {
arg = argumentValueRequired(argument);
} else if (ARGUMENT_EXTRA.equals(argument)) {
- parseBindValue(values);
+ parseBindValue(extras);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
-
}
if (uri == null) {
throw new IllegalArgumentException("Content provider URI not specified."
@@ -298,7 +311,7 @@
if (method == null) {
throw new IllegalArgumentException("Content provider method not specified.");
}
- return new CallCommand(uri, userId, method, arg, values);
+ return new CallCommand(uri, userId, method, arg, extras);
}
private GetTypeCommand parseGetTypeCommand() {
@@ -363,19 +376,22 @@
Uri uri = null;
int userId = UserHandle.USER_SYSTEM;
String[] projection = null;
- String sort = null;
- String where = null;
+ Bundle extras = new Bundle();
for (String argument; (argument = mTokenizer.nextArg())!= null;) {
if (ARGUMENT_URI.equals(argument)) {
uri = Uri.parse(argumentValueRequired(argument));
} else if (ARGUMENT_USER.equals(argument)) {
userId = Integer.parseInt(argumentValueRequired(argument));
} else if (ARGUMENT_WHERE.equals(argument)) {
- where = argumentValueRequired(argument);
+ extras.putString(ContentResolver.QUERY_ARG_SQL_SELECTION,
+ argumentValueRequired(argument));
} else if (ARGUMENT_SORT.equals(argument)) {
- sort = argumentValueRequired(argument);
+ extras.putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER,
+ argumentValueRequired(argument));
} else if (ARGUMENT_PROJECTION.equals(argument)) {
projection = argumentValueRequired(argument).split("[\\s]*:[\\s]*");
+ } else if (ARGUMENT_EXTRA.equals(argument)) {
+ parseBindValue(extras);
} else {
throw new IllegalArgumentException("Unsupported argument: " + argument);
}
@@ -384,40 +400,76 @@
throw new IllegalArgumentException("Content provider URI not specified."
+ " Did you specify --uri argument?");
}
- return new QueryCommand(uri, userId, projection, where, sort);
+ return new QueryCommand(uri, userId, projection, extras);
}
- private void parseBindValue(ContentValues values) {
+ private List<String> splitWithEscaping(String argument, char splitChar) {
+ final List<String> res = new ArrayList<>();
+ final StringBuilder cur = new StringBuilder();
+ for (int i = 0; i < argument.length(); i++) {
+ char c = argument.charAt(i);
+ if (c == '\\') {
+ if (++i == argument.length()) {
+ throw new IllegalArgumentException("Invalid escaping");
+ } else {
+ // Skip escaping char and insert next
+ c = argument.charAt(i);
+ cur.append(c);
+ }
+ } else if (c == splitChar) {
+ // Splitting char means next string
+ res.add(cur.toString());
+ cur.setLength(0);
+ } else {
+ // Copy non-escaping and non-splitting char
+ cur.append(c);
+ }
+ }
+ res.add(cur.toString());
+ return res;
+ }
+
+ private Pair<String, Object> parseBindValue() {
String argument = mTokenizer.nextArg();
if (TextUtils.isEmpty(argument)) {
throw new IllegalArgumentException("Binding not well formed: " + argument);
}
- final int firstColonIndex = argument.indexOf(COLON);
- if (firstColonIndex < 0) {
+ final List<String> split = splitWithEscaping(argument, COLON.charAt(0));
+ if (split.size() != 3) {
throw new IllegalArgumentException("Binding not well formed: " + argument);
}
- final int secondColonIndex = argument.indexOf(COLON, firstColonIndex + 1);
- if (secondColonIndex < 0) {
- throw new IllegalArgumentException("Binding not well formed: " + argument);
- }
- String column = argument.substring(0, firstColonIndex);
- String type = argument.substring(firstColonIndex + 1, secondColonIndex);
- String value = argument.substring(secondColonIndex + 1);
+ String column = split.get(0);
+ String type = split.get(1);
+ String value = split.get(2);
if (TYPE_STRING.equals(type)) {
- values.put(column, value);
+ return Pair.create(column, value);
} else if (TYPE_BOOLEAN.equalsIgnoreCase(type)) {
- values.put(column, Boolean.parseBoolean(value));
- } else if (TYPE_INTEGER.equalsIgnoreCase(type) || TYPE_LONG.equalsIgnoreCase(type)) {
- values.put(column, Long.parseLong(value));
- } else if (TYPE_FLOAT.equalsIgnoreCase(type) || TYPE_DOUBLE.equalsIgnoreCase(type)) {
- values.put(column, Double.parseDouble(value));
+ return Pair.create(column, Boolean.parseBoolean(value));
+ } else if (TYPE_INTEGER.equalsIgnoreCase(type)) {
+ return Pair.create(column, Integer.parseInt(value));
+ } else if (TYPE_LONG.equalsIgnoreCase(type)) {
+ return Pair.create(column, Long.parseLong(value));
+ } else if (TYPE_FLOAT.equalsIgnoreCase(type)) {
+ return Pair.create(column, Float.parseFloat(value));
+ } else if (TYPE_DOUBLE.equalsIgnoreCase(type)) {
+ return Pair.create(column, Double.parseDouble(value));
} else if (TYPE_NULL.equalsIgnoreCase(type)) {
- values.putNull(column);
+ return Pair.create(column, null);
} else {
throw new IllegalArgumentException("Unsupported type: " + type);
}
}
+ private void parseBindValue(ContentValues values) {
+ final Pair<String, Object> columnValue = parseBindValue();
+ values.putObject(columnValue.first, columnValue.second);
+ }
+
+ private void parseBindValue(Bundle extras) {
+ final Pair<String, Object> columnValue = parseBindValue();
+ extras.putObject(columnValue.first, columnValue.second);
+ }
+
private String argumentValueRequired(String argument) {
String value = mTokenizer.nextArg();
if (TextUtils.isEmpty(value) || value.startsWith(ARGUMENT_PREFIX)) {
@@ -500,60 +552,43 @@
private static class InsertCommand extends Command {
final ContentValues mContentValues;
+ final Bundle mExtras;
- public InsertCommand(Uri uri, int userId, ContentValues contentValues) {
+ public InsertCommand(Uri uri, int userId, ContentValues contentValues, Bundle extras) {
super(uri, userId);
mContentValues = contentValues;
+ mExtras = extras;
}
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.insert(resolveCallingPackage(), null, mUri, mContentValues, null);
+ provider.insert(resolveCallingPackage(), null, mUri, mContentValues, mExtras);
}
}
private static class DeleteCommand extends Command {
- final String mWhere;
+ final Bundle mExtras;
- public DeleteCommand(Uri uri, int userId, String where) {
+ public DeleteCommand(Uri uri, int userId, Bundle extras) {
super(uri, userId);
- mWhere = where;
+ mExtras = extras;
}
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.delete(resolveCallingPackage(), null, mUri,
- ContentResolver.createSqlQueryBundle(mWhere, null));
+ provider.delete(resolveCallingPackage(), null, mUri, mExtras);
}
}
private static class CallCommand extends Command {
final String mMethod, mArg;
- Bundle mExtras = null;
+ final Bundle mExtras;
- public CallCommand(Uri uri, int userId, String method, String arg, ContentValues values) {
+ public CallCommand(Uri uri, int userId, String method, String arg, Bundle extras) {
super(uri, userId);
mMethod = method;
mArg = arg;
- if (values != null) {
- mExtras = new Bundle();
- for (String key : values.keySet()) {
- final Object val = values.get(key);
- if (val instanceof String) {
- mExtras.putString(key, (String) val);
- } else if (val instanceof Float) {
- mExtras.putFloat(key, (Float) val);
- } else if (val instanceof Double) {
- mExtras.putDouble(key, (Double) val);
- } else if (val instanceof Boolean) {
- mExtras.putBoolean(key, (Boolean) val);
- } else if (val instanceof Integer) {
- mExtras.putInt(key, (Integer) val);
- } else if (val instanceof Long) {
- mExtras.putLong(key, (Long) val);
- }
- }
- }
+ mExtras = extras;
}
@Override
@@ -604,21 +639,20 @@
}
}
- private static class QueryCommand extends DeleteCommand {
+ private static class QueryCommand extends Command {
final String[] mProjection;
- final String mSortOrder;
+ final Bundle mExtras;
- public QueryCommand(
- Uri uri, int userId, String[] projection, String where, String sortOrder) {
- super(uri, userId, where);
+ public QueryCommand(Uri uri, int userId, String[] projection, Bundle extras) {
+ super(uri, userId);
mProjection = projection;
- mSortOrder = sortOrder;
+ mExtras = extras;
}
@Override
public void onExecute(IContentProvider provider) throws Exception {
Cursor cursor = provider.query(resolveCallingPackage(), null, mUri, mProjection,
- ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null);
+ mExtras, null);
if (cursor == null) {
System.out.println("No result found.");
return;
@@ -670,18 +704,19 @@
}
}
- private static class UpdateCommand extends InsertCommand {
- final String mWhere;
+ private static class UpdateCommand extends Command {
+ final ContentValues mValues;
+ final Bundle mExtras;
- public UpdateCommand(Uri uri, int userId, ContentValues contentValues, String where) {
- super(uri, userId, contentValues);
- mWhere = where;
+ public UpdateCommand(Uri uri, int userId, ContentValues values, Bundle extras) {
+ super(uri, userId);
+ mValues = values;
+ mExtras = extras;
}
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.update(resolveCallingPackage(), null, mUri, mContentValues,
- ContentResolver.createSqlQueryBundle(mWhere, null));
+ provider.update(resolveCallingPackage(), null, mUri, mValues, mExtras);
}
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index a2fa461..a95677d 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -406,6 +406,10 @@
mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
mOk.setEnabled(false);
+
+ if (!mOk.isInTouchMode()) {
+ mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).requestFocus();
+ }
}
/**
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index 00d0d9c..6af5fe5 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -126,17 +126,17 @@
java_library {
name: "framework-tethering-stubs-publicapi",
srcs: [":framework-tethering-stubs-srcs-publicapi"],
- sdk_version: "current",
+ defaults: ["framework-module-stubs-lib-defaults-publicapi"],
}
java_library {
name: "framework-tethering-stubs-systemapi",
srcs: [":framework-tethering-stubs-srcs-systemapi"],
- sdk_version: "system_current",
+ defaults: ["framework-module-stubs-lib-defaults-systemapi"],
}
java_library {
name: "framework-tethering-stubs-module_libs_api",
srcs: [":framework-tethering-stubs-srcs-module_libs_api"],
- sdk_version: "module_current",
+ defaults: ["framework-module-stubs-lib-defaults-systemapi"],
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 490b83f..c84892d 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -303,7 +303,8 @@
final UserManager userManager = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
- mTetheringRestriction = new UserRestrictionActionListener(userManager, this);
+ mTetheringRestriction = new UserRestrictionActionListener(
+ userManager, this, mNotificationUpdater);
mExecutor = new TetheringThreadExecutor(mHandler);
mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
@@ -432,9 +433,7 @@
// Called by wifi when the number of soft AP clients changed.
@Override
public void onConnectedClientsChanged(final List<WifiClient> clients) {
- if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, clients)) {
- reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients());
- }
+ updateConnectedClients(clients);
}
}
@@ -636,7 +635,10 @@
Context.ETHERNET_SERVICE);
synchronized (mPublicSync) {
if (enable) {
- if (mEthernetCallback != null) return TETHER_ERROR_NO_ERROR;
+ if (mEthernetCallback != null) {
+ Log.d(TAG, "Ethernet tethering already started");
+ return TETHER_ERROR_NO_ERROR;
+ }
mEthernetCallback = new EthernetCallback();
mEthernetIfaceRequest = em.requestTetheredInterface(mExecutor, mEthernetCallback);
@@ -997,11 +999,14 @@
protected static class UserRestrictionActionListener {
private final UserManager mUserManager;
private final Tethering mWrapper;
+ private final TetheringNotificationUpdater mNotificationUpdater;
public boolean mDisallowTethering;
- public UserRestrictionActionListener(UserManager um, Tethering wrapper) {
+ public UserRestrictionActionListener(@NonNull UserManager um, @NonNull Tethering wrapper,
+ @NonNull TetheringNotificationUpdater updater) {
mUserManager = um;
mWrapper = wrapper;
+ mNotificationUpdater = updater;
mDisallowTethering = false;
}
@@ -1020,13 +1025,21 @@
return;
}
- // TODO: Add user restrictions notification.
- final boolean isTetheringActiveOnDevice = (mWrapper.getTetheredIfaces().length != 0);
-
- if (newlyDisallowed && isTetheringActiveOnDevice) {
- mWrapper.untetherAll();
- // TODO(b/148139325): send tetheringSupported on restriction change
+ if (!newlyDisallowed) {
+ // Clear the restricted notification when user is allowed to have tethering
+ // function.
+ mNotificationUpdater.tetheringRestrictionLifted();
+ return;
}
+
+ // Restricted notification is shown when tethering function is disallowed on
+ // user's device.
+ mNotificationUpdater.notifyTetheringDisabledByRestriction();
+
+ // Untether from all downstreams since tethering is disallowed.
+ mWrapper.untetherAll();
+
+ // TODO(b/148139325): send tetheringSupported on restriction change
}
}
@@ -1560,6 +1573,7 @@
mIPv6TetheringCoordinator.removeActiveDownstream(who);
mOffload.excludeDownstreamInterface(who.interfaceName());
mForwardedDownstreams.remove(who);
+ updateConnectedClients(null /* wifiClients */);
// If this is a Wi-Fi interface, tell WifiManager of any errors
// or the inactive serving state.
@@ -2142,6 +2156,12 @@
return false;
}
+ private void updateConnectedClients(final List<WifiClient> wifiClients) {
+ if (mConnectedClientsTracker.updateConnectedClients(mForwardedDownstreams, wifiClients)) {
+ reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients());
+ }
+ }
+
private IpServer.Callback makeControlCallback() {
return new IpServer.Callback() {
@Override
@@ -2156,10 +2176,7 @@
@Override
public void dhcpLeasesChanged() {
- if (mConnectedClientsTracker.updateConnectedClients(
- mForwardedDownstreams, null /* wifiClients */)) {
- reportTetherClientsChanged(mConnectedClientsTracker.getLastTetheredClients());
- }
+ updateConnectedClients(null /* wifiClients */);
}
};
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java
index c3fd170..992cdd8 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java
@@ -36,6 +36,7 @@
import androidx.annotation.ArrayRes;
import androidx.annotation.DrawableRes;
+import androidx.annotation.IntDef;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
@@ -61,7 +62,9 @@
private static final boolean NOTIFY_DONE = true;
private static final boolean NO_NOTIFY = false;
// Id to update and cancel tethering notification. Must be unique within the tethering app.
- private static final int NOTIFY_ID = 20191115;
+ private static final int ENABLE_NOTIFICATION_ID = 1000;
+ // Id to update and cancel restricted notification. Must be unique within the tethering app.
+ private static final int RESTRICTED_NOTIFICATION_ID = 1001;
@VisibleForTesting
static final int NO_ICON_ID = 0;
@VisibleForTesting
@@ -85,6 +88,9 @@
// INVALID_SUBSCRIPTION_ID.
private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ @IntDef({ENABLE_NOTIFICATION_ID, RESTRICTED_NOTIFICATION_ID})
+ @interface NotificationId {}
+
public TetheringNotificationUpdater(@NonNull final Context context) {
mContext = context;
mNotificationManager = (NotificationManager) context.createContextAsUser(UserHandle.ALL, 0)
@@ -100,14 +106,14 @@
public void onDownstreamChanged(@IntRange(from = 0, to = 7) final int downstreamTypesMask) {
if (mDownstreamTypesMask == downstreamTypesMask) return;
mDownstreamTypesMask = downstreamTypesMask;
- updateNotification();
+ updateEnableNotification();
}
/** Called when active data subscription id changed */
public void onActiveDataSubscriptionIdChanged(final int subId) {
if (mActiveDataSubId == subId) return;
mActiveDataSubId = subId;
- updateNotification();
+ updateEnableNotification();
}
@VisibleForTesting
@@ -115,16 +121,31 @@
return SubscriptionManager.getResourcesForSubId(c, subId);
}
- private void updateNotification() {
+ private void updateEnableNotification() {
final boolean tetheringInactive = mDownstreamTypesMask <= DOWNSTREAM_NONE;
if (tetheringInactive || setupNotification() == NO_NOTIFY) {
- clearNotification();
+ clearNotification(ENABLE_NOTIFICATION_ID);
}
}
- private void clearNotification() {
- mNotificationManager.cancel(null /* tag */, NOTIFY_ID);
+ @VisibleForTesting
+ void tetheringRestrictionLifted() {
+ clearNotification(RESTRICTED_NOTIFICATION_ID);
+ }
+
+ private void clearNotification(@NotificationId final int id) {
+ mNotificationManager.cancel(null /* tag */, id);
+ }
+
+ @VisibleForTesting
+ void notifyTetheringDisabledByRestriction() {
+ final Resources res = getResourcesForSubId(mContext, mActiveDataSubId);
+ final String title = res.getString(R.string.disable_tether_notification_title);
+ final String message = res.getString(R.string.disable_tether_notification_message);
+
+ showNotification(R.drawable.stat_sys_tether_general, title, message,
+ RESTRICTED_NOTIFICATION_ID);
}
/**
@@ -134,8 +155,9 @@
*
* @return downstream types mask value.
*/
+ @VisibleForTesting
@IntRange(from = 0, to = 7)
- private int getDownstreamTypesMask(@NonNull final String types) {
+ int getDownstreamTypesMask(@NonNull final String types) {
int downstreamTypesMask = DOWNSTREAM_NONE;
final String[] downstreams = types.split("\\|");
for (String downstream : downstreams) {
@@ -158,8 +180,8 @@
*
* @return {@link android.util.SparseArray} with downstream types and icon id info.
*/
- @NonNull
- private SparseArray<Integer> getIcons(@ArrayRes int id, @NonNull Resources res) {
+ @VisibleForTesting
+ SparseArray<Integer> getIcons(@ArrayRes int id, @NonNull Resources res) {
final String[] array = res.getStringArray(id);
final SparseArray<Integer> icons = new SparseArray<>();
for (String config : array) {
@@ -194,12 +216,12 @@
final String title = res.getString(R.string.tethering_notification_title);
final String message = res.getString(R.string.tethering_notification_message);
- showNotification(iconId, title, message);
+ showNotification(iconId, title, message, ENABLE_NOTIFICATION_ID);
return NOTIFY_DONE;
}
private void showNotification(@DrawableRes final int iconId, @NonNull final String title,
- @NonNull final String message) {
+ @NonNull final String message, @NotificationId final int id) {
final Intent intent = new Intent(Settings.ACTION_TETHER_SETTINGS);
final PendingIntent pi = PendingIntent.getActivity(
mContext.createContextAsUser(UserHandle.CURRENT, 0),
@@ -217,6 +239,6 @@
.setContentIntent(pi)
.build();
- mNotificationManager.notify(null /* tag */, NOTIFY_ID, notification);
+ mNotificationManager.notify(null /* tag */, id, notification);
}
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringNotificationUpdaterTest.kt
new file mode 100644
index 0000000..b869491
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringNotificationUpdaterTest.kt
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2020 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.connectivity.tethering
+
+import android.app.Notification
+import android.app.NotificationManager
+import android.content.Context
+import android.content.res.Resources
+import android.net.ConnectivityManager.TETHERING_BLUETOOTH
+import android.net.ConnectivityManager.TETHERING_USB
+import android.net.ConnectivityManager.TETHERING_WIFI
+import android.os.UserHandle
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.test.BroadcastInterceptingContext
+import com.android.networkstack.tethering.R
+import com.android.server.connectivity.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+const val TEST_SUBID = 1
+const val WIFI_ICON_ID = 1
+const val USB_ICON_ID = 2
+const val BT_ICON_ID = 3
+const val GENERAL_ICON_ID = 4
+const val WIFI_MASK = 1 shl TETHERING_WIFI
+const val USB_MASK = 1 shl TETHERING_USB
+const val BT_MASK = 1 shl TETHERING_BLUETOOTH
+const val TITTLE = "Tethering active"
+const val MESSAGE = "Tap here to set up."
+const val TEST_TITTLE = "Hotspot active"
+const val TEST_MESSAGE = "Tap to set up hotspot."
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class TetheringNotificationUpdaterTest {
+ // lateinit used here for mocks as they need to be reinitialized between each test and the test
+ // should crash if they are used before being initialized.
+ @Mock private lateinit var mockContext: Context
+ @Mock private lateinit var notificationManager: NotificationManager
+ @Mock private lateinit var defaultResources: Resources
+ @Mock private lateinit var testResources: Resources
+
+ // lateinit for this class under test, as it should be reset to a different instance for every
+ // tests but should always be initialized before use (or the test should crash).
+ private lateinit var notificationUpdater: TetheringNotificationUpdater
+
+ private val ENABLE_ICON_CONFIGS = arrayOf(
+ "USB;android.test:drawable/usb", "BT;android.test:drawable/bluetooth",
+ "WIFI|BT;android.test:drawable/general", "WIFI|USB;android.test:drawable/general",
+ "USB|BT;android.test:drawable/general", "WIFI|USB|BT;android.test:drawable/general")
+
+ private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) {
+ override fun createContextAsUser(user: UserHandle, flags: Int) =
+ if (user == UserHandle.ALL) mockContext else this
+ }
+
+ private inner class WrappedNotificationUpdater(c: Context) : TetheringNotificationUpdater(c) {
+ override fun getResourcesForSubId(context: Context, subId: Int) =
+ if (subId == TEST_SUBID) testResources else defaultResources
+ }
+
+ private fun setupResources() {
+ doReturn(ENABLE_ICON_CONFIGS).`when`(defaultResources)
+ .getStringArray(R.array.tethering_notification_icons)
+ doReturn(arrayOf("WIFI;android.test:drawable/wifi")).`when`(testResources)
+ .getStringArray(R.array.tethering_notification_icons)
+ doReturn(TITTLE).`when`(defaultResources).getString(R.string.tethering_notification_title)
+ doReturn(MESSAGE).`when`(defaultResources)
+ .getString(R.string.tethering_notification_message)
+ doReturn(TEST_TITTLE).`when`(testResources).getString(R.string.tethering_notification_title)
+ doReturn(TEST_MESSAGE).`when`(testResources)
+ .getString(R.string.tethering_notification_message)
+ doReturn(USB_ICON_ID).`when`(defaultResources)
+ .getIdentifier(eq("android.test:drawable/usb"), any(), any())
+ doReturn(BT_ICON_ID).`when`(defaultResources)
+ .getIdentifier(eq("android.test:drawable/bluetooth"), any(), any())
+ doReturn(GENERAL_ICON_ID).`when`(defaultResources)
+ .getIdentifier(eq("android.test:drawable/general"), any(), any())
+ doReturn(WIFI_ICON_ID).`when`(testResources)
+ .getIdentifier(eq("android.test:drawable/wifi"), any(), any())
+ }
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ val context = TestContext(InstrumentationRegistry.getInstrumentation().context)
+ doReturn(notificationManager).`when`(mockContext)
+ .getSystemService(Context.NOTIFICATION_SERVICE)
+ notificationUpdater = WrappedNotificationUpdater(context)
+ setupResources()
+ }
+
+ private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE)
+ private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT)
+
+ private fun verifyNotification(iconId: Int = 0, title: String = "", text: String = "") {
+ verify(notificationManager, never()).cancel(any(), anyInt())
+
+ val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
+ verify(notificationManager, times(1))
+ .notify(any(), anyInt(), notificationCaptor.capture())
+
+ val notification = notificationCaptor.getValue()
+ assertEquals(iconId, notification.smallIcon.resId)
+ assertEquals(title, notification.title())
+ assertEquals(text, notification.text())
+
+ reset(notificationManager)
+ }
+
+ private fun verifyNoNotification() {
+ verify(notificationManager, times(1)).cancel(any(), anyInt())
+ verify(notificationManager, never()).notify(any(), anyInt(), any())
+
+ reset(notificationManager)
+ }
+
+ @Test
+ fun testNotificationWithDownstreamChanged() {
+ // Wifi downstream. No notification.
+ notificationUpdater.onDownstreamChanged(WIFI_MASK)
+ verifyNoNotification()
+
+ // Same downstream changed. Nothing happened.
+ notificationUpdater.onDownstreamChanged(WIFI_MASK)
+ verifyZeroInteractions(notificationManager)
+
+ // Wifi and usb downstreams. Show enable notification
+ notificationUpdater.onDownstreamChanged(WIFI_MASK or USB_MASK)
+ verifyNotification(GENERAL_ICON_ID, TITTLE, MESSAGE)
+
+ // Usb downstream. Still show enable notification.
+ notificationUpdater.onDownstreamChanged(USB_MASK)
+ verifyNotification(USB_ICON_ID, TITTLE, MESSAGE)
+
+ // No downstream. No notification.
+ notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
+ verifyNoNotification()
+ }
+
+ @Test
+ fun testNotificationWithActiveDataSubscriptionIdChanged() {
+ // Usb downstream. Showed enable notification with default resource.
+ notificationUpdater.onDownstreamChanged(USB_MASK)
+ verifyNotification(USB_ICON_ID, TITTLE, MESSAGE)
+
+ // Same subId changed. Nothing happened.
+ notificationUpdater.onActiveDataSubscriptionIdChanged(INVALID_SUBSCRIPTION_ID)
+ verifyZeroInteractions(notificationManager)
+
+ // Set test sub id. Clear notification with test resource.
+ notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
+ verifyNoNotification()
+
+ // Wifi downstream. Show enable notification with test resource.
+ notificationUpdater.onDownstreamChanged(WIFI_MASK)
+ verifyNotification(WIFI_ICON_ID, TEST_TITTLE, TEST_MESSAGE)
+
+ // No downstream. No notification.
+ notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
+ verifyNoNotification()
+ }
+
+ private fun assertIconNumbers(number: Int, configs: Array<String?>) {
+ doReturn(configs).`when`(defaultResources)
+ .getStringArray(R.array.tethering_notification_icons)
+ assertEquals(number, notificationUpdater.getIcons(
+ R.array.tethering_notification_icons, defaultResources).size())
+ }
+
+ @Test
+ fun testGetIcons() {
+ assertIconNumbers(0, arrayOfNulls<String>(0))
+ assertIconNumbers(0, arrayOf(null, ""))
+ assertIconNumbers(3, arrayOf(
+ // These configurations are invalid with wrong strings or symbols.
+ ";", ",", "|", "|,;", "WIFI", "1;2", " U SB; ", "bt;", "WIFI;USB;BT", "WIFI|USB|BT",
+ "WIFI,BT,USB", " WIFI| | | USB, test:drawable/test",
+ // This configuration is valid with two downstream types (USB, BT).
+ "USB|,,,,,|BT;drawable/test ",
+ // This configuration is valid with one downstream types (WIFI).
+ " WIFI ; android.test:drawable/xxx "))
+ }
+
+ @Test
+ fun testGetDownstreamTypesMask() {
+ assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask(""))
+ assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("1"))
+ assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("WIFI_P2P"))
+ assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("usb"))
+ assertEquals(WIFI_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI "))
+ assertEquals(USB_MASK, notificationUpdater.getDownstreamTypesMask("USB | B T"))
+ assertEquals(BT_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI: | BT"))
+ assertEquals(WIFI_MASK or USB_MASK,
+ notificationUpdater.getDownstreamTypesMask("1|2|USB|WIFI|BLUETOOTH||"))
+ }
+
+ @Test
+ fun testSetupRestrictedNotification() {
+ val title = InstrumentationRegistry.getInstrumentation().context.resources
+ .getString(R.string.disable_tether_notification_title)
+ val message = InstrumentationRegistry.getInstrumentation().context.resources
+ .getString(R.string.disable_tether_notification_message)
+ val disallowTitle = "Tether function is disallowed"
+ val disallowMessage = "Please contact your admin"
+ doReturn(title).`when`(defaultResources)
+ .getString(R.string.disable_tether_notification_title)
+ doReturn(message).`when`(defaultResources)
+ .getString(R.string.disable_tether_notification_message)
+ doReturn(disallowTitle).`when`(testResources)
+ .getString(R.string.disable_tether_notification_title)
+ doReturn(disallowMessage).`when`(testResources)
+ .getString(R.string.disable_tether_notification_message)
+
+ // User restrictions on. Show restricted notification.
+ notificationUpdater.notifyTetheringDisabledByRestriction()
+ verifyNotification(R.drawable.stat_sys_tether_general, title, message)
+
+ // User restrictions off. Clear notification.
+ notificationUpdater.tetheringRestrictionLifted()
+ verifyNoNotification()
+
+ // Set test sub id. No notification.
+ notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
+ verifyNoNotification()
+
+ // User restrictions on again. Show restricted notification with test resource.
+ notificationUpdater.notifyTetheringDisabledByRestriction()
+ verifyNotification(R.drawable.stat_sys_tether_general, disallowTitle, disallowMessage)
+ }
+}
\ No newline at end of file
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 8116f9d..5ead110 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -1072,13 +1072,15 @@
when(mUserManager.getUserRestrictions()).thenReturn(newRestrictions);
final Tethering.UserRestrictionActionListener ural =
- new Tethering.UserRestrictionActionListener(mUserManager, mockTethering);
+ new Tethering.UserRestrictionActionListener(
+ mUserManager, mockTethering, mNotificationUpdater);
ural.mDisallowTethering = currentDisallow;
ural.onUserRestrictionsChanged();
- verify(mockTethering, times(expectedInteractionsWithShowNotification))
- .untetherAll();
+ verify(mNotificationUpdater, times(expectedInteractionsWithShowNotification))
+ .notifyTetheringDisabledByRestriction();
+ verify(mockTethering, times(expectedInteractionsWithShowNotification)).untetherAll();
}
@Test
@@ -1086,7 +1088,7 @@
final String[] emptyActiveIfacesList = new String[]{};
final boolean currDisallow = false;
final boolean nextDisallow = true;
- final int expectedInteractionsWithShowNotification = 0;
+ final int expectedInteractionsWithShowNotification = 1;
runUserRestrictionsChange(currDisallow, nextDisallow, emptyActiveIfacesList,
expectedInteractionsWithShowNotification);
diff --git a/services/Android.bp b/services/Android.bp
index 490481c..52c5993 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -142,6 +142,11 @@
baseline_file: "api/lint-baseline.txt",
},
},
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system-server/api",
+ dest: "android.txt",
+ },
}
java_library {
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 74c3a9e..2783d0b 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -767,7 +767,7 @@
protected boolean connectToHal() {
synchronized (mHalLock) {
try {
- mThermalHal10 = android.hardware.thermal.V1_0.IThermal.getService();
+ mThermalHal10 = android.hardware.thermal.V1_0.IThermal.getService(true);
mThermalHal10.linkToDeath(new DeathRecipient(),
THERMAL_HAL_DEATH_COOKIE);
Slog.i(TAG,
@@ -902,7 +902,7 @@
protected boolean connectToHal() {
synchronized (mHalLock) {
try {
- mThermalHal11 = android.hardware.thermal.V1_1.IThermal.getService();
+ mThermalHal11 = android.hardware.thermal.V1_1.IThermal.getService(true);
mThermalHal11.linkToDeath(new DeathRecipient(),
THERMAL_HAL_DEATH_COOKIE);
mThermalHal11.registerThermalCallback(mThermalCallback11);
@@ -1046,7 +1046,7 @@
protected boolean connectToHal() {
synchronized (mHalLock) {
try {
- mThermalHal20 = android.hardware.thermal.V2_0.IThermal.getService();
+ mThermalHal20 = android.hardware.thermal.V2_0.IThermal.getService(true);
mThermalHal20.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
mThermalHal20.registerThermalChangedCallback(mThermalCallback20, false,
0 /* not used */);